【[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]);
        }
    }
}

 

posted @ 2018-04-05 00:25  Newuser233  阅读(6)  评论(0)    收藏  举报