社区讨论

求调treap树QWQ

灌水区参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@luhyy4xu
此快照首次捕获于
2024/04/02 13:59
2 年前
此快照最后确认于
2024/04/02 17:39
2 年前
查看原帖
RT
代码:
CPP
#include<bits/stdc++.h>
using namespace std;
int cnt=0;
struct node{
	int ls,rs,size,val,lev;
}tree[414514];
int Precursor(int u,int x){
	if(u==0) return 0;    
	if(tree[u].val>=x) return Precursor(tree[u].ls,x);   //前驱必定在左子树上 
	int n=Precursor(tree[u].rs,x);  
	if(n==0) return tree[u].val;   //x是右子树上最小的数(前驱为当前节点) 
	return n; 
}
int Successor(int u,int x){
	if(u==0) return 0;    
	if(tree[u].val<=x) return Successor(tree[u].rs,x);   //后继必定在右子树上 
	int n=Successor(tree[u].ls,x);  
	if(n==0) return tree[u].val;   //x是左子树上最大的数(后继为当前节点) 
	return n; 
}
int Rank(int u,int x){
	if(u==0) return 0;
	if(x>tree[u].val) return tree[tree[u].ls].size+1+Rank(tree[u].rs,x);
	return Rank(tree[u].ls,x);
}
int kth(int u,int k){
	if(k==tree[tree[u].ls].size+1) return tree[u].val;   //当前节点在 以这个节点为根节点的树 上排名为k
	if(k>tree[tree[u].ls].size+1) return kth(tree[u].rs,k-tree[tree[u].ls].size-1); //当前节点在 右子树 上 
	if(k<=tree[tree[u].ls].size) return kth(tree[u].ls,k); //当前节点在 左子树 上 
}
void rotate(int &o,bool d){
	int k;       //暂存旋转的节点序号
	if(d==1){
		k=tree[o].rs;
		tree[o].rs=tree[k].ls;
		tree[k].ls=o;
	}else{
		k=tree[o].ls;
		tree[o].ls=tree[k].rs;
		tree[k].rs=o;
	}
	tree[k].size=tree[o].size;
	tree[o].size=tree[tree[o].ls].size+tree[tree[o].rs].size;  //旋转之后节点的size值会有变化,所以要更新
	o=k;
	return;
}
void made(int x){
	cnt++;
	tree[cnt].ls=tree[cnt].rs=0;
	tree[cnt].val=x;
	tree[cnt].size=1;
	tree[cnt].lev=rand(); //优先级随机赋值 
	return;
}
void join(int x,int &u){
	if(u==0){
		made(x);
		u=cnt;
		return;
	}
	tree[u].size++;
	if(x>=tree[u].val) join(x,tree[u].rs);
	else join(x,tree[u].ls);
	if(tree[u].ls !=0 && tree[u].lev<tree[tree[u].ls].lev) rotate(u,1); //左旋 
	if(tree[u].rs !=0 && tree[u].lev<tree[tree[u].rs].lev) rotate(u,0); //右旋 
	tree[u].size=tree[tree[u].ls].size+tree[tree[u].rs].size; //添加之后节点的size值会有变化,所以要更新 
	return;
}
void del(int x,int &u){
	tree[u].size--;
	if(tree[u].val==x){
		if(tree[u].ls==0&&tree[u].rs==0) u=0;//可以试试size==0 
		else if(tree[u].ls==0||tree[u].rs==0) u=tree[u].ls+tree[u].rs;//u的左(右)节点代替u
		else if(tree[tree[u].ls].lev>tree[tree[u].rs].lev){
			rotate(u,0);
			del(x,tree[u].rs);
		}else{
			rotate(u,1);
			del(x,tree[u].ls);
		}
		return;
	}
	if(tree[u].val>=x) del(x,tree[u].ls);
	else del(x,tree[u].rs);
	tree[u].size=tree[tree[u].ls].size+tree[tree[u].rs].size; //日常更新 
	return;
}
int main(){
	srand(time(NULL));
	int n;
	cin>>n;
	int root=0;
	while(n--){
		int cz,x;
		cin>>cz>>x;
		if(cz==1) join(x,root);
		if(cz==2) del(x,root);
		if(cz==3) cout<<Rank(root,x)+1<<endl;
		if(cz==4) cout<<kth(root,x)<<endl;
		if(cz==5) cout<<Precursor(root,x)<<endl;
		if(cz==6) cout<<Successor(root,x)<<endl;
	}
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...