首页 > 其他分享 >FHQ treap(再见splay------)

FHQ treap(再见splay------)

时间:2024-07-05 10:34:13浏览次数:6  
标签:rt large int son splay treap ------ inline now

但凡打过平衡树的应该都知道\(\huge{二逼平衡树}\)这道题,抄了两个小时的splay版题解,然后发现了\(\color{maroon}FHQ treap\):

$\large\color{green}这是splay$
struct jjtree
{
	inline void up(rint x){sz[x]=sz[son[x][0]]+sz[son[x][1]]+cnt[x];}
	inline bool so(rint x){return x==son[fa[x]][1];}
	inline void clear(rint x){fa[x]=son[x][0]=son[x][1]=cnt[x]=v[x]=sz[x]=0;}
	inline void xuan(rint x){
		rint y=fa[x],z=fa[y];bool op=so(x);
		son[y][op]=son[x][op^1];if(son[y][op])fa[son[y][op]]=y;
		son[x][op^1]=y,fa[y]=x;if(z)son[z][y==son[z][1]]=x;fa[x]=z;
		up(x),up(y);
	}
	inline void splay(rint x,rint y=0){
		if(!y)rt=x;
		while(fa[x]!=y){
			rint k1=fa[x];
			if(fa[k1]!=y)xuan(so(x)==so(k1)?k1:x);
			xuan(x);
		}
	}
	inline void insert(int x){
		if(!rt){
			v[++tot]=x;
			++cnt[tot];rt=tot;up(rt);return;
		}
		int now=rt,f=0;
		while(1){
			// cout<<now<<endl;
			if(v[now]==x){
				++cnt[now];up(now);up(f);splay(now);return;
			}
			f=now,now=son[now][x>v[now]];
			if(!now){
				v[++tot]=x,++cnt[tot],fa[tot]=f;
				son[f][x>v[f]]=tot;up(tot),up(f),splay(tot);
				return;
			}
		}
	}
	inline int rk(int x){
		int ans=0,now=rt;
		while(1){
			if(x<v[now])now=son[now][0];
			else{
				ans+=sz[son[now][0]];
				if(!now)return ans+1;
				if(x==v[now])return splay(now),ans+1;
				ans+=cnt[now],now=son[now][1];
			}
		}
	}
	inline int kth(int k){
		int now=rt;
		while(1){
			if(son[now][0]&&k<=sz[son[now][0]])now=son[now][0];
			else{
				k-=sz[son[now][0]]+cnt[now];
				if(k<=0)return splay(now),v[now];
				now=son[now][1];
			}
		}
	}
	inline int pre(){
		int now=son[rt][0];
		if(!now)return 0;
		while(son[now][1])now=son[now][1];
		splay(now);
		return now;
	}
	inline int nxt(){
		int now=son[rt][1];
		if(!now)return 0;
		while(son[now][0])now=son[now][0];
		splay(now);
		return now;
	}
	inline void del(int k){
		rk(k);
		// if(v[rt]!=k)return;
		if(cnt[rt]>1)return --cnt[rt],up(rt),(void)(0);
		if(!son[rt][0]&&!son[rt][1])return clear(rt),rt=0,(void)0;
		if(!son[rt][0]){
			int now=rt;rt=son[rt][1];fa[rt]=0;clear(now);return;
		}
		if(!son[rt][1]){
			int now=rt;rt=son[rt][0];fa[rt]=0;clear(now);return;
		}
		int now=rt,x=pre();
		fa[son[now][1]]=x;son[x][1]=son[now][1];
		clear(now);up(rt);
	}
}tr;
$\large{总长91行}$
$\large\color{green}这是FHQ treap$
struct jj{
	int son[N][2],sz[N],v[N],id[N],tot,rt;
	inline void up(int x){sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;}
	inline int ne(int x){return sz[++tot]=1,v[tot]=x,id[tot]=rand(),tot;}
	inline int he(int x,int y){
		if(!x||!y)return x^y;
		if(id[x]<id[y]){return son[x][1]=he(son[x][1],y),up(x),x;}
		return son[y][0]=he(x,son[y][0]),up(y),y;
	}
	inline void fen(int now,int k,int &x,int &y){
		if(!now)x=y=0;
		else{
			if(k>=v[now])x=now,fen(son[now][1],k,son[now][1],y);
			else y=now,fen(son[now][0],k,x,son[now][0]);
			up(now);
		}
	}
	inline int kth(int now,int k){
		while(1){
			if(k<=sz[son[now][0]])now=son[now][0];
			else if(k==sz[son[now][0]]+1)return now;
			else k-=sz[son[now][0]]+1,now=son[now][1];
		}
	}
	inline void ins(int k){
		int x,y;
		fen(rt,k,x,y),rt=he(he(x,ne(k)),y);
	}
	inline void del(int k){
		int x,y,z;
		fen(rt,k,x,y),fen(x,k-1,x,z);
		z=he(son[z][0],son[z][1]),rt=he(he(x,z),y);
	}
	inline int rk(int k){
		int x,y,ans;
		fen(rt,k-1,x,y);ans=sz[x]+1;
		return rt=he(x,y),ans;
	}
	inline int pre(int k){
		int x,y,ans;
		fen(rt,k-1,x,y);ans=v[kth(x,sz[x])];
		return rt=he(x,y),ans;
	}
	inline int nxt(int k){
		int x,y,ans;
		fen(rt,k,x,y);ans=v[kth(y,1)];
		return rt=he(x,y),ans;
	}
}tr[2];
$\large{总长48行}$

\[\]

\[\]

\[\]

\[\]

终于知道什么是$$\huge\color{seagreen}{相见恨晚}$$


\[\]

\[\]

\[\]

闲言少叙,开始摞码

\[\]

\[\]

\[\]

\(\huge\color{purple}{FHQ treap}\)

\[\]

\[\]

\(\large \color{salmon}{即无旋treap,同时维护着堆和二叉树的性质,支持splay、treap可支持的一切操作,而且更方便}\)

\[\]

\(\large\color{maroon}维护信息其他平衡树基本相同\)

struct jj{
    int son[N][2],sz[N],tot,rt,id[N],v[N];
	//son[i][0]->ls(i),son[i][1]-> rs(i)
	//sz[i]->  以i为根节点的树的大小
	//id[i]->  rand()出来的,用来维护堆的性质
	//v[i] i点存的权值
	//tot-> 所有存在过的点的个数,主要用来新建一个点
	//rt -> 这棵树的根
	inline void up(int x){sz[x]=sz[son[x][0]]+sz[son[x][1]]+1;}//update
	inline int ne(int x){return sz[++tot]=1,v[tot]=x,id[tot]=rand(),tot;}//新建一个点
}tr[2];

\[\]

\[\]

\[\]

\(\large \color{maroon}{FHQ只需要两个操作:合并与分裂}\)

\(\large{合并}:\)

\[\]

\(\large\color{salmon} 根据随机给的id,为了保持堆的性质,让id小的在上面\)

inline int he(int x,int y){
        if(!x||!y)return x^y;
        if(id[x]<id[y])return son[x][1]=he(son[x][1],y),up(x),x;
        return son[y][0]=he(x,son[y][0]),up(y),y;
}

\[\]

\(\large{分裂:}\)

\[\]

\(\large\color{salmon}{把一棵树分成小于等于k,和大于k的两部分}\)

inline void fen(int now,int k,int &x,int &y){
        if(!now)x=y=0;//叶子节点,不要忘记清空
        else{
            if(k>=v[now])x=now,fen(son[now][1],k,son[now][1],y);//now及其左子树都可以归到x中,然后继续向下fen
            else y=now,fen(son[now][0],k,x,son[now][0]);//now及其右字数都可以归到y中,继续fen
            up(now);//别忘up
        }
    }

\[\]

\[\]

\(\large\color{maroon}{会了合并与分裂就可以进行各种操作了}\)

\[\]

\(\large \cal{insert}:\)

\(\large\color{salmon}以k为界定值,将树分为两部分x和y,并在x,y中间插入一个权值为k的节点,将他们合并起来\)

inline void ins(int k){
    int x,y;
    fen(rt,k,x,y),rt=he(he(x,ne(k)),y);
}

\[\]

\(\large \cal{delete}:\)

\(\large\color{salmon}以k为界定值分为x,y,再以k-1为界定值将x分为x,z,那么z中所有节点都是权值为k,删除z根节点,再将他们合并起来即可\)

inline void del(int k){
    int x,y,z;
    fen(rt,k,x,y),fen(x,k-1,x,z);
    z=he(son[z][0],son[z][1]),rt=he(he(x,z),y);
}

\[\]

\(\large \cal{kth}:\)

\(\large\color{salmon}在以now为根的树中,排名为k的节点\)

inline int kth(int now,int k){
    while(1){
        if(k<=sz[son[now][0]])now=son[now][0];
        else if(k==sz[son[now][0]]+1)return now;
        else k-=sz[son[now][0]]+1,now=son[now][1];
    }
}

\[\]

\(\large \cal{rank}:\)

inline int rk(int k){
    int x,y,ans;
    fen(rt,k-1,x,y);ans=sz[x]+1;
    return rt=he(x,y),ans;
}

\[\]

\(\large \cal{pre\ and \ next}:\)

inline int pre(int k){
    int x,y,ans;
    fen(rt,k-1,x,y);ans=v[kth(x,sz[x])];
    return rt=he(x,y),ans;
}
inline int nxt(int k){
    int x,y,ans;
    fen(rt,k+1,x,y);ans=v[kth(x,)];
    return rt=he(x,y),ans;
}

\[\huge\color{purple}{FHQ \ treap \ 好用 \ 爱用} \]

标签:rt,large,int,son,splay,treap,------,inline,now
From: https://www.cnblogs.com/GGrun-sum/p/18285036

相关文章

  • Qt实现汽车仪表盘
    在UI界面显示中,仪表盘的应用相对比较广泛,经常用于显示速度值,电压电流值等等,最终实现效果如下动态图片(文末提供给源工程下载): 主要包含以下绘制步骤:绘制画布/**绘制画布*/voidWidget::initCanvas(QPainter&painter){//消除锯齿painter.setRenderHint(QPai......
  • 使用EasyExcel的AnalysisEventListener读取EXCEL导入数据
    1、实体对象VOimportcom.alibaba.excel.annotation.ExcelProperty;importlombok.Data;@DatapublicclassPrizeLogImportExcelVO{@ExcelProperty("订单编号")privateStringprizeSn;@ExcelProperty("快递公司")privateStringexpressN......
  • qt 入门常用类理解(涉及QMessageBox,Layout,Spacers,Splitter,Buuddy,LoginApp,QFile,
    1.QMessageBoxQMessageBox::Yes QApplication::quit();QMessageBox::exec用于在模态(阻塞式)对话框中显示一个消息框,并等待用户的响应。这个函数通常用于在应用程序中显示消息、警告或询问对话框,并等待用户采取适当的操作后继续执行。int QMessageBox::exec()exec 函数没有......
  • Python速通(输入输出)
    1.(牛牛最喜欢的语言)牛牛认为Python是世界上最好的语言,因为Python是一种简单、方便、易学习的语言,牛牛最喜欢Python了!现在请你输出字符串"Pythonisthebestlanguage!"表达牛牛对Python的喜爱。print("Pythonisthebestlanguage!")2.(冲击offer的牛牛)即将毕业的牛牛在牛......
  • Python数据分析代码示例
    数据清洗在进行数据分析之前,通常需要对原始数据进行清洗,即处理缺失值、异常值、重复值等问题。下面是一个数据清洗的示例代码:importpandasaspd#读取原始数据data=pd.read_csv('data.csv')#处理缺失值data=data.dropna()#处理异常值data=data[data['value'......
  • 【规范】Git分支管理,看看我司是咋整的
    前言......
  • 连接池(示例:GO)
    连接池(ConnectionPool)是一种用于管理和复用数据库连接或其他资源连接的技术。通过连接池,应用程序可以避免频繁创建和销毁连接,从而提高性能和资源利用效率。连接池的主要目标是减少连接的创建和销毁开销,提供一个连接复用机制。一、连接池的工作原理初始化连接池:启动时,连......
  • nvidia&QM9700&9790 ib NDR交换机FAQ
    一、交换机简介:基于NVIDIAquantum-2的QM9700和QM9790交换系统提供64个逻辑端口,在1U标准机箱设计中,每个逻辑端口400Gb/sib,支持32个800G/sOSFP光模块,支持最新的NDR技术,NVIDIAQuantum-2带来了一个高速、极低延迟和可扩展的解决方案,其中包含最先进的技术,如远程直接内存访问(RD......
  • 小国王 骑士 状态压缩DP
    //小国王.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>#include<vector>usingnamespacestd;/*https://loj.ac/p/10170http://ybt.ssoier.cn:8088/problem_show.php?pid=1592在nxn的棋盘上放k个国王,国王可攻击相邻的......
  • AntDesign上传组件upload二次封装+全局上传hook使用
    文章目录前言a-upload组件二次封装1.功能分析2.代码+详细注释3.使用到的全局上传hook代码4.使用方式5.效果展示总结前言在项目中,ant-design是我们常用的UI库之一,今天就来二次封装常用的组件a-upload批量上传组件,让它用起来更方便。a-upload组件二次封装1.......