您的位置:首页 > 其它

bzoj 3224 普通平衡树

2016-07-17 17:41 267 查看
算是平衡树最好的入门模板题了,几乎涵盖了平衡树所有的基础操作.

当然也可以用vector强行乱搞(毕竟暴力出奇迹).

splay

#include<cstdio>
#define N 200005
using namespace std;
int son
[3],num
[3],f
,a
;
int opt,n,i,root,x,node,ans,flag;
inline void Rotate(int x,int w)//1:左旋;2:右旋 w==1
{
int y=f[x],z=f[y];
son[y][3-w]=son[x][w];
if (son[x][w]) f[son[x][w]]=y;
f[x]=z;
num[y][3-w]=num[x][w];
num[x][w]+=num[y][w]+1;
if (z)
{
if (y==son[z][1]) son[z][1]=x;
else son[z][2]=x;
}
f[y]=x;son[x][w]=y;
}
inline void splay(int x)
{
int y;
while (f[x])
{
y=f[x];
if (!f[y])
{
if (x==son[y][1]) Rotate(x,2);else Rotate(x,1);
continue;
}
if (y==son[f[y]][1])
{
if (x==son[y][1]) Rotate(y,2),Rotate(x,2);
else Rotate(x,1),Rotate(x,2);
}
else
{
if (x==son[y][2]) Rotate(y,1),Rotate(x,1);
else Rotate(x,2),Rotate(x,1);
}
}
root=x;
}
inline void inser(int x,int add)
{
if (add<=a[x])
{
if (!son[x][1]) son[x][1]=++node,a[node]=add,f[node]=x;
else inser(son[x][1],add);
num[x][1]++;
}
else
{
if (!son[x][2]) son[x][2]=++node,a[node]=add,f[node]=x;
else inser(son[x][2],add);
num[x][2]++;
}
}
inline void del(int x,int add)
{
if (!x) return;
if (add==a[x])
{
splay(x);
if (!son[x][1]&&!son[x][2]){root=0;return;}
if (!son[x][1]) {root=son[x][2];f[son[x][2]]=0;return;}
if (!son[x][2]) {root=son[x][1];f[son[x][1]]=0;return;}
int find=son[x][1],temp=son[x][2];
while (son[find][2]) find=son[find][2];
splay(find);son[find][2]=temp;f[temp]=find;
return;
}
if (add<a[x]) del(son[x][1],add);else del(son[x][2],add);
}
inline int T_T(int x,int add,int now)
{
inser(root,add);splay(node);
int ans=num[node][1]+1;
del(node,add);
return ans;
}
inline int O_O(int x,int k)
{
if (k==num[x][1]+1) return a[x];
if (k<=num[x][1]) return O_O(son[x][1],k);
return O_O(son[x][2],k-num[x][1]-1);
}
inline int qian(int x,int k)
{
int find=son[x][1];if (!find) return 0;
while (son[find][2]) find=son[find][2];
if (a[find]!=k) flag=1;return find;
}
inline int hou(int x,int k)
{
int find=son[x][2];if (!find) return 0;
while (son[find][1]) find=son[find][1];
if (a[find]!=k) flag=1;return find;
}
int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
scanf("%d",&n);root=0;
for (i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
if (opt==1) inser(root,x),splay(node);
if (opt==2) del(root,x);
if (opt==3) printf("%d\n",T_T(root,x,0));
if (opt==4) printf("%d\n",O_O(root,x));
if (opt==5)
{
inser(root,x);splay(node);
for (flag=0,ans=qian(root,x);!flag||!ans;splay(ans),ans=qian(root,x));
del(root,x);printf("%d\n",a[ans]);
}
if (opt==6)
{
inser(root,x);splay(node);
for (flag=0,ans=hou(root,x);!flag||!ans;splay(ans),ans=hou(root,x));
del(root,x);printf("%d\n",a[ans]);
}
}
return 0;
}


treap和vector不怎么会,如果想知道的话,详见hzwer的博客.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  splay