一个模板splay
①申明:
int key[120000],f[120000],v[120000],size[120000],ch[120000][2],sz,root;
// key[i]--节点i所表示的数字 f[i]--i的父节点 size[i]--i节点的子树大小(包括i)
// v[i]--key[i]出现的次数 ch[i][0]--i的左儿子 ch[i][1]--i的右儿子 sz整棵树大小 root整棵树的根
②各个操作
void clear(int x) //清理
{
key[x]=f[x]=v[x]=size[x]=ch[x][0]=ch[x][1]=0;
}
int get(int x)//求x是f[x]的左儿子还是右儿子
{
return ch[f[x]][1]==x;
}
void updata(int x)//操作导致修改后要更新
{
if (x)
{
size[x]=v[x];
size[x]+=size[ch[x][0]];
size[x]+=size[ch[x][1]];
}
}
void rotate(int x)//将x旋转成他父节点的父节点
{
int fa=f[x]; int gf=f[fa]; int which=get(x);
ch[fa][which]=ch[x][which^1]; f[ch[fa][which]]=fa;//如果他是父节点的左儿子,则转后父节点无左儿子,他无右儿子,所以他右儿子接上父节点,反之亦然
f[fa]=x;ch[x][which^1]=fa; f[x]=gf;
if (gf) ch[gf][ch[gf][1]==fa]=x;
updata(fa); updata(x);
}
void splay(int x)//将x旋转至根
{
for (int fa;(fa=f[x]);rotate(x))
if (f[fa])
{
int a=get(fa); int b=get(x);
if (a==b) rotate(fa);else rotate(x);//如果父节点,祖父节点,和x一线了,先转父节点
}
root=x;
}
void insert(int x)//插入
{
int now=root; int fa=0;
if (root==0) {sz++;ch[sz][1]=ch[sz][0]=0;f[sz]=0;key[sz]=x;v[sz]=1;size[sz]=1;root=sz;return;}
while(1)
{
if (key[now]==x){v[now]++;updata(now);updata(fa);splay(now);break;}
fa=now;
now=ch[now][key[now]<x];
if (now==0)
{
sz++;
ch[sz][0]=ch[sz][1]=0; v[sz]=1; key[sz]=x; size[sz]=1; f[sz]=fa;
ch[fa][key[fa]<x]=sz;
updata(fa);
splay(sz);
break;
}
}
}
int find(int x)// 求x的排名
{
int ans=0; int now=root;
while(1)
{
if (x<key[now])
now=ch[now][0];
else
{
ans+=size[ch[now][0]];
if (x==key[now]){splay(now);return ans+1;}
ans+=v[now];
now=ch[now][1];
}
}
}
int findx(int x)//求排名为x的数
{
int now=root;
while(1)
{
if (ch[now][0]&& x<=size[ch[now][0]])
now=ch[now][0];
else
{
int temp=size[ch[now][0]]+v[now];
if (x<=temp) return key[now];
x-=temp; now=ch[now][1];
}
}
}
int pre()//求根的左子树的最大的数
{
int now=ch[root][0];
while(ch[now][1]) now=ch[now][1];
return now;
}
int next()//求根的右子树的最小的数
{
int now =ch[root][1];
while(ch[now][0]) now=ch[now][0];
return now;
}
void del(int x)//删除x
{
int haha=find(x);
if (v[root]>1) {v[root]--;return;}
if (!ch[root][1]&&!ch[root][0]) {clear(root);root=0;return ;}
if (!ch[root][1]) {int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;}
if (!ch[root][0]) {int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;}
int lb=pre(),oldroot=root;
splay(lb);
f[ch[oldroot][1]]=root;
f[root]=0;
ch[root][1]=ch[oldroot][1];
clear(oldroot);
updata(root);
return;
}