• 【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;
    }
  • 相关阅读:
    Qt class加载头文件
    Qt 中KeyPressEvent获取不到Key_Space等事件
    如何选择开源许可证?
    C语言实现库函数汇总
    简单背包问题-递归非递归实现
    中点优先顺序遍历数组-递归非递归实现
    稀疏矩阵十字链表表示
    稀疏矩阵线性表示
    KMP模式匹配
    双向链表
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793541.html
Copyright © 2020-2023  润新知