【BZOJ1861】书架(ZJOI2006)-平衡树复健题

测试地址:书架
做法:好久没做平衡树的题了,结果一道水题写了一晚上……唉……
这一道题需要用到平衡树。
这一题可以按书的编号建点,然后给每个点附上一个优先值,那么按优先值从小到大排序就是当前书架上书的顺序了。题目中的几个操作就可以写成这样:
Top和Bottom操作:将一个点的优先值赋成比当前所有点优先值都小(或者都大),然后重新插入该点。
Insert操作:将相邻两个点的优先值交换,然后重新插入。
Ask和Query操作:经典的求某点排名或求某排名的点的操作。
以上这些操作就明显可以用平衡树维护了。
以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100000
using namespace std;

int n,m,nowmn,nowmx,rt;
int val[N+10],siz[N+10],ch[N+10][2],fa[N+10];
char op[15];

void debug()
{
    printf("===debug===
");
    for(int i=1;i<=n+2;i++)
        printf("%d %d %d %d
",ch[i][0],ch[i][1],fa[i],siz[i]);
}

void pushup(int v)
{
    siz[v]=siz[ch[v][0]]+siz[ch[v][1]]+1;
}

void rotate(int x,bool f)
{
    int y=fa[x];
    ch[y][!f]=ch[x][f];
    fa[ch[x][f]]=y;
    ch[x][f]=y;
    if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x;
    fa[x]=fa[y];
    fa[y]=x;
    pushup(y);
}

void Splay(int x,int goal)
{
    while(fa[x]!=goal)
    {
        if (fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x);
        else
        {
            int y=fa[x],z=fa[fa[x]];
            bool f=(ch[y][1]==x);
            if (ch[z][f]==y) rotate(y,!f),rotate(x,!f);
            else rotate(x,!f),rotate(x,f);
        }
    }
    pushup(x);
    if (!goal) rt=x;
}

void insert(int &v,int now,int f)
{
    if (!v)
    {
        v=now;
        fa[v]=f;
        siz[v]=1;
        ch[v][0]=ch[v][1]=0;
        Splay(v,0);
        return;
    }
    siz[v]++;
    insert(ch[v][val[now]>val[v]],now,v);
}

int rank(int v)
{
    Splay(v,0);
    return siz[ch[v][0]]+1;
}

int query(int x)
{
    int v=rt;
    while(siz[ch[v][0]]+1!=x)
    {
        if (siz[ch[v][0]]+1<x) x-=siz[ch[v][0]]+1,v=ch[v][1];
        else v=ch[v][0];
    }
    return v;
}

void Delete(int v)
{
    int r=rank(v);
    Splay(query(r-1),0);
    Splay(query(r+1),rt);
    siz[rt]--,siz[ch[rt][1]]--;
    ch[ch[rt][1]][0]=0;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        val[x]=i;
    }

    rt=n+1;
    nowmn=1,nowmx=n;
    fa[n+1]=0,siz[n+1]=2,ch[n+1][0]=0,ch[n+1][1]=n+2,val[n+1]=-10000000;
    fa[n+2]=n+1,siz[n+2]=1,ch[n+2][0]=ch[n+2][1]=0,val[n+2]=10000000;
    siz[0]=0;
    for(int i=1;i<=n;i++)
        insert(rt,i,0);

    for(int i=1;i<=m;i++)
    {
        int s,t;
        scanf("%s",op);
        scanf("%d",&s);
        if (op[0]=='T')
        {
            Delete(s);
            val[s]=--nowmn;
            insert(rt,s,0);
        }
        if (op[0]=='B')
        {
            Delete(s);
            val[s]=++nowmx;
            insert(rt,s,0);
        }
        if (op[0]=='I')
        {
            scanf("%d",&t);
            if (!t) {Splay(s,0);continue;}
            int x=query(rank(s)+t);
            Delete(s);
            Delete(x);
            swap(val[s],val[x]);
            insert(rt,s,0);
            insert(rt,x,0);
        }
        if (op[0]=='A')
        {
            printf("%d
",rank(s)-2);
        }
        if (op[0]=='Q')
        {
            printf("%d
",t=query(s+1));
            Splay(t,0);
        }
    }

    return 0;
}
原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793541.html