【BZOJ】3224 Tyvj 1728 普通平衡树 平衡树模板

[置顶] 【BZOJ】3224 Tyvj 1728 普通平衡树 平衡树模板

标签: POJ平衡树难题c语言
143人阅读 评论(3) 收藏 举报
本文章已收录于:
分类:

好吧,我承认,我患有帕金森:手贱啊,打错一个字符,把if (t[k].w<x)打成了if (t[k].w>x)结果只得了20分。(泪流满面,55555……)

这道题考察的是平衡树的模板,只有一些平衡树的基本操作,相信只要对平衡树有一些了解的同学就能把这题A掉。

做这道题,权当是复习一下平衡树的模板,为接下来的平衡树的学习和刷题打下基础。

今天我主要讲的是Treap。Treap,顾名思义,就是tree(二叉搜索树)+heap(堆),Treap这种数据结构即有二叉搜索树的有序性,并给予每个节点一个随机键值,用堆的方式来维护整棵树的平衡,防止了二叉搜索树退化成一条链,每次查找的时间复杂度变成了O(n),使二叉搜索树的查找的时间复杂度保持在O(log(n))左右。虽然对于一些较小的n,这个优化并不是非常明显,但是随着n的增大,Treap就会在效率上碾压二叉搜索树。

Treap的基本操作有以下6个:

1、插入:将一个数插入Treap中,并使Treap的二叉搜索树和堆的性质保持不变。

2、删除:将一个数从Treap中删除,并使Treap的二叉搜索树和堆的性质保持不变。

3、求一个数在Treap变成一个有序序列后的排名

4、求在Treap变成一个有序序列后一个位置上的数

5、求一个数的前驱

6、求一个数的后继

在维护Treap的堆性质的时候,会有一个操作:旋转,就是把随机键值进行维护堆的性质的操作。Treap的旋转操作比Splay要简单。

其实Treap说起来十分容易,但是敲起代码来却并不简单,代码量还是非常大的。

“以后打代码的时候一定要十分的认真。“不要把代码的准确度寄托在调试上,只有靠自己清晰的思路。”——oyqy

不多说了,大家自己看吧。附上AC代码:

  1. #include <cstdio>  
  2. #include <cstdlib>  
  3. using namespace std;  
  4.   
  5. struct note{  
  6.     int w,size,rnd,g;  
  7. }t[100010];  
  8. int n,son[100010][2],x,y,root,size,ans;  
  9.   
  10. void turn(int &k,int x){  
  11.     int p=son[k][x];  
  12.     son[k][x]=son[p][x^1];  
  13.     son[p][x^1]=k;  
  14.     t[p].size=t[k].size;  
  15.     t[k].size=t[son[k][0]].size+t[son[k][1]].size+t[k].g;  
  16.     k=p;  
  17.     return;  
  18. }  
  19.   
  20. void insert(int &k,int x){  
  21.     if (k==0){  
  22.         k=++size;  
  23.         t[k].w=x;  
  24.         t[k].rnd=rand();  
  25.         t[k].g=t[k].size=1;  
  26.         return;  
  27.     }  
  28.     ++t[k].size;  
  29.     if (t[k].w==x) ++t[k].g;  
  30.     else   
  31.     if (t[k].w<x){  
  32.         insert(son[k][1],x);  
  33.         if (t[son[k][1]].rnd<t[k].rnd) turn(k,1);  
  34.     }  
  35.     else {  
  36.         insert(son[k][0],x);  
  37.         if (t[son[k][0]].rnd<t[k].rnd) turn(k,0);  
  38.     }  
  39. }  
  40.   
  41. void del(int &k,int x){  
  42.     if (k==0) return;  
  43.     if (t[k].w==x){  
  44.         if (t[k].g>1){  
  45.             --t[k].g;  
  46.             --t[k].size;  
  47.             return;  
  48.         }  
  49.         if (son[k][0]*son[k][1]==0) k=son[k][0]+son[k][1];  
  50.         else   
  51.         if (t[son[k][0]].rnd<t[son[k][1]].rnd) turn(k,0),del(k,x);  
  52.         else turn(k,1),del(k,x);  
  53.     }  
  54.     else {  
  55.         --t[k].size;  
  56.         if (t[k].w<x) del(son[k][1],x);  
  57.         else del(son[k][0],x);  
  58.     }  
  59.     return;  
  60. }  
  61.   
  62. int query_pos(int k,int x){  
  63.     if (k==0) return 0;  
  64.     if (t[k].w==x)   
  65.         return t[son[k][0]].size+1;  
  66.     else   
  67.     if (t[k].w<x)  
  68.         return t[son[k][0]].size+t[k].g+query_pos(son[k][1],x);  
  69.     else   
  70.         return query_pos(son[k][0],x);  
  71. }  
  72.   
  73. int query_num(int k,int x){  
  74.     if (k==0) return 0;  
  75.     if (t[son[k][0]].size>=x)  
  76.         return query_num(son[k][0],x);  
  77.     else   
  78.     if (t[son[k][0]].size+t[k].g<x)  
  79.         return query_num(son[k][1],x-t[son[k][0]].size-t[k].g);  
  80.     else   
  81.         return t[k].w;  
  82. }  
  83.   
  84. void query_pre(int k,int x){  
  85.     if (k==0) return;  
  86.     if (t[k].w<x) ans=k,query_pre(son[k][1],x);  
  87.         else query_pre(son[k][0],x);  
  88. }  
  89.   
  90. void query_bac(int k,int x){  
  91.     if (k==0) return;  
  92.     if (t[k].w>x) ans=k,query_bac(son[k][0],x);  
  93.         else query_bac(son[k][1],x);  
  94. }  
  95.   
  96. int main(void){  
  97.     scanf("%d",&n);  
  98.     for (int i=1; i<=n; ++i){  
  99.         scanf("%d%d",&x,&y);  
  100.         switch (x){  
  101.             case 1:insert(root,y);break;  
  102.             case 2:del(root,y);break;  
  103.             case 3:printf("%d\n",query_pos(root,y));break;  
  104.             case 4:printf("%d\n",query_num(root,y));break;  
  105.             case 5:query_pre(root,y);printf("%d\n",t[ans].w);ans=0;break;  
  106.             case 6:query_bac(root,y);printf("%d\n",t[ans].w);ans=0;break;  
  107.         }  
  108.     }  
  109.     return 0;  
  110. }  
#include <cstdio>
#include <cstdlib>
using namespace std;

struct note{
	int w,size,rnd,g;
}t[100010];
int n,son[100010][2],x,y,root,size,ans;

void turn(int &k,int x){
	int p=son[k][x];
	son[k][x]=son[p][x^1];
	son[p][x^1]=k;
	t[p].size=t[k].size;
	t[k].size=t[son[k][0]].size+t[son[k][1]].size+t[k].g;
	k=p;
	return;
}

void insert(int &k,int x){
	if (k==0){
		k=++size;
		t[k].w=x;
		t[k].rnd=rand();
		t[k].g=t[k].size=1;
		return;
	}
	++t[k].size;
	if (t[k].w==x) ++t[k].g;
	else 
	if (t[k].w<x){
		insert(son[k][1],x);
		if (t[son[k][1]].rnd<t[k].rnd) turn(k,1);
	}
	else {
		insert(son[k][0],x);
		if (t[son[k][0]].rnd<t[k].rnd) turn(k,0);
	}
}

void del(int &k,int x){
	if (k==0) return;
	if (t[k].w==x){
		if (t[k].g>1){
			--t[k].g;
			--t[k].size;
			return;
		}
		if (son[k][0]*son[k][1]==0) k=son[k][0]+son[k][1];
		else 
		if (t[son[k][0]].rnd<t[son[k][1]].rnd) turn(k,0),del(k,x);
		else turn(k,1),del(k,x);
	}
	else {
		--t[k].size;
		if (t[k].w<x) del(son[k][1],x);
		else del(son[k][0],x);
	}
	return;
}

int query_pos(int k,int x){
	if (k==0) return 0;
	if (t[k].w==x) 
		return t[son[k][0]].size+1;
	else 
	if (t[k].w<x)
		return t[son[k][0]].size+t[k].g+query_pos(son[k][1],x);
	else 
		return query_pos(son[k][0],x);
}

int query_num(int k,int x){
	if (k==0) return 0;
	if (t[son[k][0]].size>=x)
		return query_num(son[k][0],x);
	else 
	if (t[son[k][0]].size+t[k].g<x)
		return query_num(son[k][1],x-t[son[k][0]].size-t[k].g);
	else 
		return t[k].w;
}

void query_pre(int k,int x){
	if (k==0) return;
	if (t[k].w<x) ans=k,query_pre(son[k][1],x);
		else query_pre(son[k][0],x);
}

void query_bac(int k,int x){
	if (k==0) return;
	if (t[k].w>x) ans=k,query_bac(son[k][0],x);
		else query_bac(son[k][1],x);
}

int main(void){
	scanf("%d",&n);
	for (int i=1; i<=n; ++i){
		scanf("%d%d",&x,&y);
		switch (x){
			case 1:insert(root,y);break;
			case 2:del(root,y);break;
			case 3:printf("%d\n",query_pos(root,y));break;
			case 4:printf("%d\n",query_num(root,y));break;
			case 5:query_pre(root,y);printf("%d\n",t[ans].w);ans=0;break;
			case 6:query_bac(root,y);printf("%d\n",t[ans].w);ans=0;break;
		}
	}
	return 0;
}

3.30更新:

听Manchery大神的指导,我又重新认识了treap的终极版:非旋转treap。

虽然在洛谷和BZOJ上测出来都要比旋转式的慢,但是非旋转treap可以可持久化,所以还是有学习的必要的。

测评感悟:O2优化真的是个好东西,我在没有开O2的洛谷上测出来用了1000ms+,而在开了O2的BZOJ上只用了500ms+。

附上AC代码:

  1. #include <cstdio>  
  2. #include <algorithm>  
  3. using namespace std;  
  4.   
  5. typedef pair<int,int> p;  
  6. struct note{  
  7.     int ls,rs,w,rnd,size;  
  8. }t[100010];  
  9. int ti,x,o,root,len;  
  10.   
  11. void updata(int k){  
  12.     t[k].size=t[t[k].ls].size+t[t[k].rs].size+1;  
  13. }  
  14.   
  15. p fl(int k,int x){  
  16.     if (x==0) return make_pair(0,k);  
  17.     int ls=t[k].ls,rs=t[k].rs;  
  18.     if (x==t[ls].size) return t[k].ls=0,updata(k),make_pair(ls,k);  
  19.     if (x==t[ls].size+1) return t[k].rs=0,updata(k),make_pair(k,rs);  
  20.     if (x<t[ls].size){  
  21.         p tmp=fl(ls,x);  
  22.         return t[k].ls=tmp.second,updata(k),make_pair(tmp.first,k);  
  23.     }  
  24.     p tmp=fl(rs,x-t[ls].size-1);  
  25.     return t[k].rs=tmp.first,updata(k),make_pair(k,tmp.second);  
  26. }  
  27.   
  28. int hb(int x,int y){  
  29.     if (x==0||y==0) return x+y;  
  30.     if (t[x].rnd<t[y].rnd) return t[x].rs=hb(t[x].rs,y),updata(x),x;  
  31.         else return t[y].ls=hb(x,t[y].ls),updata(y),y;  
  32. }  
  33.   
  34. int wz(int k,int x){  
  35.     int ans=0,tmp=2e9;  
  36.     while (k){  
  37.         if (x==t[k].w) tmp=min(tmp,ans+t[t[k].ls].size+1);  
  38.         if (x>t[k].w) ans+=t[t[k].ls].size+1,k=t[k].rs;  
  39.             else k=t[k].ls;  
  40.     }  
  41.     return tmp==2e9?ans:tmp;  
  42. }  
  43.   
  44. int fd(int k,int x){  
  45.     while (1){  
  46.         if (t[t[k].ls].size==x-1) return t[k].w;  
  47.         if (t[t[k].ls].size>x-1) k=t[k].ls;  
  48.             else x-=t[t[k].ls].size+1,k=t[k].rs;  
  49.     }  
  50. }  
  51.   
  52. void ist(int x){  
  53.     int k=wz(root,x);  
  54.     p tmp=fl(root,k);  
  55.     t[++len].w=x;  
  56.     t[len].rnd=rand();  
  57.     t[len].size=1;  
  58.     root=hb(tmp.first,len);  
  59.     root=hb(root,tmp.second);  
  60. }  
  61.   
  62. void del(int x){  
  63.     int k=wz(root,x);  
  64.     p t1=fl(root,k),t2=fl(t1.first,k-1);  
  65.     root=hb(t2.first,t1.second);  
  66. }  
  67.   
  68. int pre(int k,int x){  
  69.     int ans=-2e9;  
  70.     while (k)  
  71.         if (t[k].w<x) ans=max(ans,t[k].w),k=t[k].rs;  
  72.             else k=t[k].ls;  
  73.     return ans;  
  74. }  
  75.   
  76. int bac(int k,int x){  
  77.     int ans=2e9;  
  78.     while (k)  
  79.         if (t[k].w>x) ans=min(ans,t[k].w),k=t[k].ls;  
  80.             else k=t[k].rs;  
  81.     return ans;  
  82. }  
  83.   
  84. int main(void){  
  85.     scanf("%d",&ti);  
  86.     while (ti--){  
  87.         scanf("%d%d",&o,&x);  
  88.         switch (o){  
  89.             case 1:ist(x);break;  
  90.             case 2:del(x);break;  
  91.             case 3:printf("%d\n",wz(root,x));break;  
  92.             case 4:printf("%d\n",fd(root,x));break;  
  93.             case 5:printf("%d\n",pre(root,x));break;  
  94.             case 6:printf("%d\n",bac(root,x));break;  
  95.         }  
  96.     }  
  97.     return 0;  
  98. }  
#include <cstdio>
#include <algorithm>
using namespace std;

typedef pair<int,int> p;
struct note{
	int ls,rs,w,rnd,size;
}t[100010];
int ti,x,o,root,len;

void updata(int k){
	t[k].size=t[t[k].ls].size+t[t[k].rs].size+1;
}

p fl(int k,int x){
	if (x==0) return make_pair(0,k);
	int ls=t[k].ls,rs=t[k].rs;
	if (x==t[ls].size) return t[k].ls=0,updata(k),make_pair(ls,k);
	if (x==t[ls].size+1) return t[k].rs=0,updata(k),make_pair(k,rs);
	if (x<t[ls].size){
		p tmp=fl(ls,x);
		return t[k].ls=tmp.second,updata(k),make_pair(tmp.first,k);
	}
	p tmp=fl(rs,x-t[ls].size-1);
	return t[k].rs=tmp.first,updata(k),make_pair(k,tmp.second);
}

int hb(int x,int y){
	if (x==0||y==0) return x+y;
	if (t[x].rnd<t[y].rnd) return t[x].rs=hb(t[x].rs,y),updata(x),x;
		else return t[y].ls=hb(x,t[y].ls),updata(y),y;
}

int wz(int k,int x){
	int ans=0,tmp=2e9;
	while (k){
		if (x==t[k].w) tmp=min(tmp,ans+t[t[k].ls].size+1);
		if (x>t[k].w) ans+=t[t[k].ls].size+1,k=t[k].rs;
			else k=t[k].ls;
	}
	return tmp==2e9?ans:tmp;
}

int fd(int k,int x){
	while (1){
		if (t[t[k].ls].size==x-1) return t[k].w;
		if (t[t[k].ls].size>x-1) k=t[k].ls;
			else x-=t[t[k].ls].size+1,k=t[k].rs;
	}
}

void ist(int x){
	int k=wz(root,x);
	p tmp=fl(root,k);
	t[++len].w=x;
	t[len].rnd=rand();
	t[len].size=1;
	root=hb(tmp.first,len);
	root=hb(root,tmp.second);
}

void del(int x){
	int k=wz(root,x);
	p t1=fl(root,k),t2=fl(t1.first,k-1);
	root=hb(t2.first,t1.second);
}

int pre(int k,int x){
	int ans=-2e9;
	while (k)
		if (t[k].w<x) ans=max(ans,t[k].w),k=t[k].rs;
			else k=t[k].ls;
	return ans;
}

int bac(int k,int x){
	int ans=2e9;
	while (k)
		if (t[k].w>x) ans=min(ans,t[k].w),k=t[k].ls;
			else k=t[k].rs;
	return ans;
}

int main(void){
	scanf("%d",&ti);
	while (ti--){
		scanf("%d%d",&o,&x);
		switch (o){
			case 1:ist(x);break;
			case 2:del(x);break;
			case 3:printf("%d\n",wz(root,x));break;
			case 4:printf("%d\n",fd(root,x));break;
			case 5:printf("%d\n",pre(root,x));break;
			case 6:printf("%d\n",bac(root,x));break;
		}
	}
	return 0;
}

5.27更新:


总是听其他大佬说起Splay有多好,但是由于我太菜了,一直都不会Splay。

昨天决定要好好学学Splay,对着Splay的模板就是一顿抄。

但可惜还是不能完全理解代码的意思,还是要多加思考和理解。


本来是昨天就想写这篇博客的,但是有同学让我去帮他改代码,所以推迟到今天来写了。

唉,自己还是太菜,帮别人一个左偏树的代码竟然花掉了我一个小时的时间……


今天在看这篇自己写的博客,发现只有旋转型的Treap还依稀记得一点,非旋转的Treap已是完全忘记。

蒟蒻还是要多复习自己之前所学,不然只能被其他大佬虐。


今日学习心得:%%%法老大佬,困扰我一个晚上的问题他只用了五分钟就解决了——我的代码一直输出太多或太少。

原来是因为我读入优化的问题,我为了节省代码量,把处理负数的变量f定义为char类型的,然后在char类型前加了一个static。

说起来static到现在我还不知道是用来干什么用的,但是听其他大佬说好像可以使代码的运行速度变快,所以就经常性的加上去了。

结果可想而知,就是这里出错了……

好像是因为static char f只能定义,不能修改之类的问题导致我没有办法读入负数,然后就毫无疑问的一直WA了。

“没事就不要用那些自己不熟练的东西,这些东西并没有什么卵用,没法提升很多的运行速度,只是为了装13罢了。”——法老大神。


附上AC代码:

  1. #include <cstdio>  
  2. #include <cctype>  
  3. #define N 100010  
  4. using namespace std;  
  5.   
  6. struct tree{  
  7.     int w,size,g,f;  
  8. }t[N<<1];  
  9. int n,o,y,rt,size,ch[N][2];  
  10.   
  11. inline char nc(){  
  12.     static char ch[100010],*p1=ch,*p2=ch;  
  13.     return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;  
  14. }  
  15.   
  16. inline void read(int& a){  
  17.     static char c=nc();int f=1;  
  18.     for (;!isdigit(c);c=nc()) if (c=='-') f=-1;  
  19.     for (a=0;isdigit(c);a=a*10+c-'0',c=nc());  
  20.     a*=f;return;  
  21. }  
  22.   
  23. inline void updata(int x){  
  24.     if (x){  
  25.         t[x].size=t[x].g;  
  26.         if (ch[x][0]) t[x].size+=t[ch[x][0]].size;  
  27.         if (ch[x][1]) t[x].size+=t[ch[x][1]].size;  
  28.     }  
  29. }  
  30.   
  31. inline bool get(int x){  
  32.     return ch[t[x].f][1]==x;  
  33. }  
  34.   
  35. inline void rotate(int x){  
  36.     int fa=t[x].f,ffa=t[fa].f,op=get(x);  
  37.     ch[fa][op]=ch[x][op^1],t[ch[fa][op]].f=fa;  
  38.     ch[x][op^1]=fa,t[fa].f=x;  
  39.     t[x].f=ffa;  
  40.     if (ffa) ch[ffa][ch[ffa][1]==fa]=x;  
  41.     return updata(fa),updata(x);  
  42. }  
  43.   
  44. inline void splay(int x){  
  45.     for (int fa;fa=t[x].f;rotate(x))  
  46.         if (t[fa].f) rotate((get(x)==get(fa))?fa:x);  
  47.     rt=x;return;  
  48. }  
  49.   
  50. inline void ist(int x){  
  51.     if (!rt){  
  52.         rt=++size;  
  53.         ch[size][0]=ch[size][1]=t[size].f=0;  
  54.         t[size].size=t[size].g=1,t[size].w=x;  
  55.         return;  
  56.     }  
  57.     int now=rt,fa=0;  
  58.     while (1){  
  59.         if (x==t[now].w){  
  60.             ++t[now].g,updata(now),updata(fa),splay(now);  
  61.             break;  
  62.         }  
  63.         fa=now,now=ch[now][t[now].w<x];  
  64.         if (!now){  
  65.             ch[fa][t[fa].w<x]=++size;  
  66.             ch[size][0]=ch[size][1]=0;  
  67.             t[size].f=fa,t[size].size=t[size].g=1,t[size].w=x;  
  68.             updata(fa),splay(size);  
  69.             break;  
  70.         }  
  71.     }  
  72.     return;  
  73. }  
  74.   
  75. inline void clean(int x){  
  76.     ch[x][0]=ch[x][1]=t[x].w=t[x].f=t[x].g=t[x].size=0;  
  77. }  
  78.   
  79. inline int find(int x){  
  80.     int now=rt,ans=0;  
  81.     while (1){  
  82.         if (x<t[now].w) now=ch[now][0];  
  83.         else {  
  84.             ans+=(ch[now][0]?t[ch[now][0]].size:0);  
  85.             if (x==t[now].w) {  
  86.                 splay(now);  
  87.                 return ans+1;  
  88.             }  
  89.             ans+=t[now].g;  
  90.             now=ch[now][1];  
  91.         }  
  92.     }  
  93. }  
  94.   
  95. inline int findx(int x){  
  96.     int now=rt;  
  97.     while (1){  
  98.         if (ch[now][0]&&x<=t[ch[now][0]].size) now=ch[now][0];  
  99.         else {  
  100.             int tmp=(ch[now][0]?t[ch[now][0]].size:0)+t[now].g;  
  101.             if (x<=tmp) return t[now].w;  
  102.             x-=tmp,now=ch[now][1];  
  103.         }  
  104.     }  
  105. }  
  106.   
  107. inline int pre(){  
  108.     int now=ch[rt][0];  
  109.     while (ch[now][1]) now=ch[now][1];  
  110.     return now;  
  111. }  
  112.   
  113. inline int bac(){  
  114.     int now=ch[rt][1];  
  115.     while (ch[now][0]) now=ch[now][0];  
  116.     return now;  
  117. }  
  118.   
  119. inline void del(int x){  
  120.     find(x);  
  121.     if (t[rt].g>1){  
  122.         --t[rt].g,updata(rt);  
  123.         return;  
  124.     }  
  125.     if (!ch[rt][0]&&!ch[rt][1]){  
  126.         clean(rt),rt=0;  
  127.         return;  
  128.     }  
  129.     if (!ch[rt][0]||!ch[rt][1]){  
  130.         int p=rt;  
  131.         rt=ch[rt][0]+ch[rt][1],t[rt].f=0,clean(p);  
  132.         return;  
  133.     }  
  134.     int q=pre(),p=rt;  
  135.     splay(q),ch[rt][1]=ch[p][1],t[ch[p][1]].f=rt;  
  136.     return clean(p),updata(rt);  
  137. }  
  138.   
  139. int main(void){  
  140.     read(n);  
  141.     while (n--){  
  142.         read(o); read(y);  
  143.         switch(o){  
  144.             case 1: ist(y); break;  
  145.             case 2: del(y); break;  
  146.             case 3: printf("%d\n",find(y)); break;  
  147.             case 4: printf("%d\n",findx(y)); break;  
  148.             case 5: ist(y); printf("%d\n",t[pre()].w); del(y); break;  
  149.             case 6: ist(y); printf("%d\n",t[bac()].w); del(y); break;  
  150.         }  
  151.     }  
  152. }  
#include <cstdio>
#include <cctype>
#define N 100010
using namespace std;

struct tree{
	int w,size,g,f;
}t[N<<1];
int n,o,y,rt,size,ch[N][2];

inline char nc(){
	static char ch[100010],*p1=ch,*p2=ch;
	return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int& a){
	static char c=nc();int f=1;
	for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
	for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
	a*=f;return;
}

inline void updata(int x){
	if (x){
		t[x].size=t[x].g;
		if (ch[x][0]) t[x].size+=t[ch[x][0]].size;
		if (ch[x][1]) t[x].size+=t[ch[x][1]].size;
	}
}

inline bool get(int x){
	return ch[t[x].f][1]==x;
}

inline void rotate(int x){
	int fa=t[x].f,ffa=t[fa].f,op=get(x);
	ch[fa][op]=ch[x][op^1],t[ch[fa][op]].f=fa;
	ch[x][op^1]=fa,t[fa].f=x;
	t[x].f=ffa;
	if (ffa) ch[ffa][ch[ffa][1]==fa]=x;
	return updata(fa),updata(x);
}

inline void splay(int x){
	for (int fa;fa=t[x].f;rotate(x))
		if (t[fa].f) rotate((get(x)==get(fa))?fa:x);
	rt=x;return;
}

inline void ist(int x){
	if (!rt){
		rt=++size;
		ch[size][0]=ch[size][1]=t[size].f=0;
		t[size].size=t[size].g=1,t[size].w=x;
		return;
	}
	int now=rt,fa=0;
	while (1){
		if (x==t[now].w){
			++t[now].g,updata(now),updata(fa),splay(now);
			break;
		}
		fa=now,now=ch[now][t[now].w<x];
		if (!now){
			ch[fa][t[fa].w<x]=++size;
			ch[size][0]=ch[size][1]=0;
			t[size].f=fa,t[size].size=t[size].g=1,t[size].w=x;
			updata(fa),splay(size);
			break;
		}
	}
	return;
}

inline void clean(int x){
	ch[x][0]=ch[x][1]=t[x].w=t[x].f=t[x].g=t[x].size=0;
}

inline int find(int x){
	int now=rt,ans=0;
	while (1){
		if (x<t[now].w) now=ch[now][0];
		else {
			ans+=(ch[now][0]?t[ch[now][0]].size:0);
			if (x==t[now].w) {
				splay(now);
				return ans+1;
			}
			ans+=t[now].g;
			now=ch[now][1];
		}
	}
}

inline int findx(int x){
	int now=rt;
	while (1){
		if (ch[now][0]&&x<=t[ch[now][0]].size) now=ch[now][0];
		else {
			int tmp=(ch[now][0]?t[ch[now][0]].size:0)+t[now].g;
			if (x<=tmp) return t[now].w;
			x-=tmp,now=ch[now][1];
		}
	}
}

inline int pre(){
	int now=ch[rt][0];
	while (ch[now][1]) now=ch[now][1];
	return now;
}

inline int bac(){
	int now=ch[rt][1];
	while (ch[now][0]) now=ch[now][0];
	return now;
}

inline void del(int x){
	find(x);
	if (t[rt].g>1){
		--t[rt].g,updata(rt);
		return;
	}
	if (!ch[rt][0]&&!ch[rt][1]){
		clean(rt),rt=0;
		return;
	}
	if (!ch[rt][0]||!ch[rt][1]){
		int p=rt;
		rt=ch[rt][0]+ch[rt][1],t[rt].f=0,clean(p);
		return;
	}
	int q=pre(),p=rt;
	splay(q),ch[rt][1]=ch[p][1],t[ch[p][1]].f=rt;
	return clean(p),updata(rt);
}

int main(void){
	read(n);
	while (n--){
		read(o); read(y);
		switch(o){
			case 1: ist(y); break;
			case 2: del(y); break;
			case 3: printf("%d\n",find(y)); break;
			case 4: printf("%d\n",findx(y)); break;
			case 5: ist(y); printf("%d\n",t[pre()].w); del(y); break;
			case 6: ist(y); printf("%d\n",t[bac()].w); del(y); break;
		}
	}
}

0
0
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值