fhq Treap模板21分求调
查看原帖
fhq Treap模板21分求调
1068165
InfiniteRobin楼主2024/8/6 12:38
#include<bits/stdc++.h>
using namespace std;

const int N=1e6+5;

int n,m,idx=0;
int x,y,z,root;
int opt;

struct node{
	int l,r;  //左右子树 
	int num;  //数字 
	int size; //大小 
	int val;  //权值 
}tr[N];

int new_node(int x){  //新建节点 
	tr[++idx].num=x;  //数字赋值 
	tr[idx].size=1;  //大小赋值 
	tr[idx].val=rand();  //随机权值 
	return idx;  //返回编号 
}

void pushup(int x){  //更新值 
	tr[x].size=1 + tr[tr[x].l].size + tr[tr[x].r].size;
} 

//分裂 
void split(int p,int num,int &x,int &y){  //根节点 数值 小于值的子树的根  大于值的子树的根 
	if(!p){  //如果不存在 
		x=y=0;
		return;
	}
	if(tr[p].num > x){  //如果在左子树 
		y=p;
		split(tr[p].l,num,x,tr[p].l);
	}
	else{  //右子树 
		x=p;
		split(tr[p].r,num,tr[p].r,y);
	}
	pushup(p);
}

//合并 
int merge(int x,int y){  //根  根 一定要满足 x 的数值小于 y 的数值 
	if(!x||!y){  //如果有空树 
		return x+y;
	}
	if(tr[x].size < tr[y].size){  //大根堆 
		tr[x].r=merge(tr[x].r,y);  //把 y 归入 x 的右子树 
		pushup(x);
		return x;
	}
	else{
		tr[y].l=merge(x,tr[y].l);  //把 x 归入 y 的左子树 
		pushup(y);
		return y;
	}
}

void insert(int num){  //插入新节点 
	split(root,num,x,y);  //把树分割为 小于 num  和大于 num 两棵树 
	root=merge( merge(x , new_node(num)) ,y);  //按大小合并 
}  
 
void del(int num){ //删除 
	split(root,num,x,y);  //分成 小于等于 大于 两部分 
	split(x,num-1,x,z);  // x 分成 小于 num 和 等于 num
	z=merge(tr[z].l,tr[z].r); //删除 num 的根节点 
	root=merge(merge(x,z),y); //恢复回去 
}

int num_to_rank(int num){  //找排名 
	split(root,num-1,x,y); //分成 小于 num 和 大于等于 
	int ans=tr[x].size+1;  //答案就是 左子树 +1 
	root=merge(x,y);
	return ans;
}

int rank_to_num(int p,int rank){  //找数字 
	if(tr[tr[p].l].size+1==rank){  //找到 
		return tr[p].num;
	}
	else if(tr[tr[p].l].size+1 > rank){  //在左子树 
		return rank_to_num(tr[p].l,rank);
	}
	else{ //否则在右子树 
		return rank_to_num(tr[p].r,rank-tr[tr[p].l].size-1);
	}
}

int pre(int num){
	split(root,num-1,x,y); //前驱 
	int p=x,ans; //答案在 左子树 
//	while(tr[p].r){ //一直往右跳 找最大 
//		p=tr[p].r;
//	}
//	ans=tr[p].num;
	ans=rank_to_num(x,tr[x].size); 
	root=merge(x,y);
	return ans;
}

int after(int num){ //后继 
	split(root,num,x,y); 
	int p=y,ans; //答案在右子树 
//	while(tr[p].l){ //一直往左跳 
//		p=tr[p].l;
//	}
//	ans=tr[p].num;
	ans=rank_to_num(y,1); 
	root=merge(x,y);
	return ans;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);

	cin>>n;
	while(n--){
		cin>>opt>>x;
		if(opt==1) insert(x);  //插入 
		if(opt==2) del(x);    //删除 
		if(opt==3) cout<<num_to_rank(x)<<endl;  //查询 x 的排名 
		if(opt==4) cout<<rank_to_num(root,x)<<endl; //查询第 x 名的数 
		if(opt==5) cout<<pre(x)<<endl;  //查 小于 x 的最大数 
		if(opt==6) cout<<after(x)<<endl; //查 大于 x 的最小数 
	}
	return 0;
}
2024/8/6 12:38
加载中...