有旋Treap求调
查看原帖
有旋Treap求调
941178
BenRheinz楼主2024/1/1 18:33

rt ,对着书和同学老师的 AC 代码找了好几遍,没找出问题所在。评测记录,求助神犇。

#include<bits/stdc++.h> 
using namespace std;
const int maxn=1e5+5,inf=1e9+114514;
//treap: 这棵树需要同时满足大根堆和二叉搜索树的性质 
mt19937 rnd(0);//随机数
struct node{
	int l,r;
	int val,dat;
	int cnt,size;
} tr[maxn]; 
int root,tot;
int newnode(int val){
	tr[++tot].val=val,tr[tot].dat=rnd();
	tr[tot].cnt=tr[tot].size=1;
	return tot;
}
inline void pushup(int p){
	tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+tr[p].cnt;
}
void zig(int &p){
	//将 p 点的左子树绕 p 顺时针旋转为 p 的父节点 
	int q=tr[p].l;
	tr[p].l=tr[q].r,tr[q].r=p;
	p=q;
	pushup(tr[p].r),pushup(p);
}
void zag(int &p){
	//将 p 点的右子树绕 p 逆时针旋转为 p 的父节点 
	int q=tr[p].r;
	tr[p].r=tr[q].l,tr[q].l=p;
	p=q;
	pushup(tr[p].l),pushup(p);
}
void build(){
	newnode(-inf),newnode(inf);
	tr[1].r=2,root=1;
	if(tr[2].dat>tr[1].dat) swap(tr[1].dat,tr[2].dat);
}
int getrank(int p,int val){
	if(p==0) return 1;
	if(val==tr[p].val) return tr[tr[p].l].size+1;
	if(val<tr[p].val) return getrank(tr[p].l,val);
	return tr[tr[p].l].size+tr[p].cnt+getrank(tr[p].r,val);
}
int getval(int p,int Rank){
	if(p==0) return inf;
	if(tr[tr[p].l].size>=Rank) return getval(tr[p].l,Rank);
	if(tr[tr[p].l].size+tr[p].cnt>=Rank) return tr[p].val;
	return getval(tr[p].r,Rank-tr[tr[p].l].size-tr[p].cnt);
}
void insert(int &p,int val){
	if(p==0){
		p=newnode(val);
		return;
	}
	if(tr[p].val==val) tr[p].cnt++;
	else if(val<tr[p].val){
		insert(tr[p].l,val); 
		if(tr[tr[p].l].dat>tr[p].dat) zig(p);
	} else {
		insert(tr[p].r,val);
		if(tr[tr[p].r].dat>tr[p].dat) zag(p);
	}
	pushup(p);
}
void remove(int &p,int val){
	if(p==0) return;
	if(tr[p].val==val){
		if(tr[p].cnt>1){
			tr[p].cnt--,pushup(p);
			return;
		}
		if(tr[p].l||tr[p].r){
			if(tr[p].r==0||tr[tr[p].l].dat>tr[tr[p].r].dat) zig(p),remove(tr[p].r,val);
			else zag(p),remove(tr[p].l,val);
			pushup(p);
		} else p=0;
		return;
	}
	if(val<tr[p].val) remove(tr[p].l,val);
	else remove(tr[p].r,val);
	pushup(p);
}
int pre(int val){
	int ans=1,p=root;
	while(p){
		if(tr[p].val==val){
			if(tr[p].l>0){
				p=tr[p].l;
				while(tr[p].r>0) p=tr[p].r;
				ans=p;
			}
			break;
		}
		if(tr[p].val<val&&tr[p].val>tr[ans].val) ans=p;
		p=val<tr[p].val?tr[p].l:tr[p].r;
	}
	return tr[ans].val;
}
int nxt(int val){
	int ans=2,p=root;
	while(p){
		if(tr[p].val==val){
			if(tr[p].r>0){
				p=tr[p].r;
				while(tr[p].l>0) p=tr[p].l;
				ans=p;
			}
			break;
		}
		if(tr[p].val>val&&tr[p].val<tr[ans].val) ans=p;
		p=val<tr[p].val?tr[p].l:tr[p].r;
	}
	return tr[ans].val;
}
int main(){
	int n;
	scanf("%d",&n);
	build();
	int op,x;
	while(n--){
		scanf("%d %d",&op,&x);
		if(op==1) insert(root,x);
		else if(op==2) remove(root,x);
		else if(op==3) printf("%d\n",getrank(root,x)-1);
		else if(op==4) printf("%d\n",getval(root,x+1));
		else if(op==5) printf("%d\n",pre(x));
		else printf("%d\n",nxt(x));
	}
	return 0;
}
2024/1/1 18:33
加载中...