【[ZJOI2006]书架】splay板题
一道平衡树板题调了两个小时,我真是太弱了
传送门:https://www.luogu.org/problemnew/show/P2596
我们一个一个操作地来分解
top: 先splay那个结点,然后将root左子树全部放在后继的左子树里面(注意特判没有左右子树的情况)
bottom:类同top,只是将root右子树全部放在前驱的右子树里面
insert: 0相当没有操作,1或-1则先splay后,root与前驱或后继交换位置,记得交换值和pos值
Ask;splay后左子树size Query:直接find找出第K个位置的编号返回值
看上去分解起来是不是很简单? 然后智障如我开始想得很复杂,如top和bottom要找到前驱后继后将前驱后继进行合并,各种先后操作位置搞错,真是太菜了。。。
#include<bits/stdc++.h>
#define zig(x) zigzag(x,1)
#define zag(x) zigzag(x,2)
using namespace std;
const int maxn = 80005;
int n,m,fa[maxn<<1],siz[maxn<<1],tot,ls[maxn<<1],rs[maxn<<1],dat[maxn<<1],root,pos[maxn];
void putup(int x)
{
siz[x]=siz[ls[x]]+siz[rs[x]]+1;
}
void zigzag(int x,int knd)
{
int y=fa[x]; int z=fa[y];
if(z)
{
if(ls[z]==y) ls[z]=x;
else rs[z]=x;
}
fa[x]=z; fa[y]=x;
if(knd==1)
{
ls[y]=rs[x];
fa[ls[y]]=y;
rs[x]=y;
}
else
{
rs[y]=ls[x];
fa[rs[y]]=y;
ls[x]=y;
}
putup(y); putup(x);
}
void splay(int x)
{
int y,z;
while(fa[x])
{
y=fa[x]; z=fa[y];
if(z)
{
if(ls[z]==y)
{
if(ls[y]==x) { zig(y); zig(x); }
else { zag(x); zig(x); }
}
else
{
if(rs[y]==x) { zag(y); zag(x); }
else { zig(x); zag(x); }
}
}
else
{
if(ls[y]==x) zig(x);
else zag(x);
}
}
root=x;
}
void ins(int x)
{
if(!tot) { ++tot; dat[tot]=x; root=tot; siz[tot]=1; return ; }
++tot;
int p=root;
while(rs[p]) { siz[p]++; p=rs[p];}
siz[p]++; rs[p]=tot;
siz[tot]=1; dat[tot]=x; fa[tot]=p; splay(tot);
}
int getmax(int x)
{
while(rs[x]) x=rs[x];
return x;
}
int getmin(int x)
{
while(ls[x]) x=ls[x];
return x;
}
int fin(int k)
{
int p=root;
while(p)
{
if(k==siz[ls[p]]+1) break;
else if(siz[ls[p]]>=k) p=ls[p];
else { k-=(siz[ls[p]]+1); p=rs[p]; }
}
return dat[p];
}
int main()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&x); ins(x); pos[x]=i;
}
char ss[10];
for(int i=1;i<=m;i++)
{
scanf("%s%d",ss,&x);
if(ss[0]=='Q')
{
printf("%d\n",fin(x));
}
else if(ss[0]=='T')
{
splay(pos[x]);
if(!ls[root]) continue;
if(!rs[root]) {rs[root]=ls[root]; ls[root]=0; continue;}
int y=getmin(rs[root]);
fa[ls[root]]=y;
ls[y]=ls[root]; ls[root]=0;
splay(y);
}
else if(ss[0]=='B')
{
splay(pos[x]);
if(!rs[root]) continue;
if(!ls[root]) { ls[root]=rs[root]; rs[root]=0; continue; }
int y=getmax(ls[root]);
fa[rs[root]]=y;
rs[y]=rs[root]; rs[root]=0;
splay(y);
}
else if(ss[0]=='A')
{
splay(pos[x]); printf("%d\n",siz[ls[root]]);
}
else //if(ss[0]=='I')
{
int t;
scanf("%d",&t);
if(t==0) continue;
else if(t==1)
{
splay(pos[x]);
y=getmin(rs[root]);
}
else if(t==-1)
{
splay(pos[x]);
y=getmax(ls[root]);
}
int tmp=pos[x];
swap(pos[dat[y]],pos[x]);
swap(dat[y],dat[tmp]);
}
}
}

浙公网安备 33010602011771号