zoukankan      html  css  js  c++  java
  • [BZOJ 1861] 书架

    Link:

    BZOJ 1861 传送门

    Solution:

    一道平衡树裸题调了两小时真是**

    操作都比较常规:

    1、$Top,Bottom$操作

    先将$x$转到根节点,分情况讨论将其左/右子树合并到另一边去

    2、$Insert$操作

    其实完全没有必要先删除再插入,直接将$x$与其前驱/后继的信息交换就好了

    Tip:

    1、总感觉自己几个量分不清:点的序号,点的权值,点的排名(即在序列中的次序)

    此题中$pos[x]$由权值指向序号,因此只有交换节点时改变,其他时候不用更新

    2、一般要对节点进行操作都要将其先旋转到根节点,感觉自己老忘……

    3、如果对交换前的值有调用,一定要将原值先存下来!

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    const int MAXN=1e5+10;
    char s[20];int x,y;
    int n,m,rt,dat[MAXN],ch[MAXN][2],f[MAXN],sz[MAXN],pos[MAXN],val[MAXN],tot=0;
    
    void pushup(int x)
    {sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
    
    void Build(int l,int r,int anc)
    {
        if(l>r) return;
        int mid=(l+r)/2;
        if(mid<anc) ch[anc][0]=mid;
        else ch[anc][1]=mid;
        f[mid]=anc;sz[mid]=1;
        val[mid]=dat[mid];pos[dat[mid]]=mid;
        
        Build(l,mid-1,mid);Build(mid+1,r,mid);
        pushup(mid);
    }
    
    void Rotate(int x)
    {
        int y=f[x],z=f[y],k=(ch[y][1]==x);
        ch[z][ch[z][1]==y]=x;f[x]=z;
        ch[y][k]=ch[x][k^1];f[ch[x][k^1]]=y;
        ch[x][k^1]=y;f[y]=x;
        pushup(x);pushup(y);
    }
    
    void Splay(int x,int up)
    {
        while(f[x]!=up)
        {
            int y=f[x],z=f[y];
            if(z!=up) (ch[y][1]==x)^(ch[z][1]==y)?Rotate(x):Rotate(y);
            Rotate(x);
        }
        if(!up) rt=x;
    }
    
    int Kth(int x)
    {
        int k=rt;
        while(true)
        {
            if(sz[ch[k][0]]+1==x) return k;
            else if(sz[ch[k][0]]>=x) k=ch[k][0];
            else x-=sz[ch[k][0]]+1,k=ch[k][1];
        }
    }
    
    void Top(int x)
    {
        x=pos[x];Splay(x,0);
        if(!ch[x][0]) return;
        if(!ch[x][1]){ch[x][1]=ch[x][0];ch[x][0]=0;return;}
        int y=Kth(sz[ch[x][0]]+2);
        ch[y][0]=ch[x][0];f[ch[x][0]]=y;ch[x][0]=0;
        Splay(y,0);
    }
    
    void Bottom(int x)
    {
        x=pos[x];Splay(x,0);
        if(!ch[x][1]) return;
        if(!ch[x][0]){ch[x][0]=ch[x][1];ch[x][1]=0;return;}
        int y=Kth(sz[ch[x][0]]);
        ch[y][1]=ch[x][1];f[ch[x][1]]=y;ch[x][1]=0;
        Splay(y,0);
    }
    
    void Move(int x,int flag)
    {
        if(!flag) return;
        Splay(pos[x],0);//一定要先Splay 
        int y=Kth(flag==1?sz[ch[pos[x]][0]]+2:sz[ch[pos[x]][0]]);
        int t=pos[x];//一定要先保留,否则再调用pos[x]时其值就变了 
        swap(pos[x],pos[val[y]]);
        swap(val[t],val[y]);
    }
    
    int Ask(int x)
    {Splay(pos[x],0);return sz[ch[rt][0]];}
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&dat[i]);
        rt=(n+1)/2;Build(1,n,rt);f[rt]=0;
        
        for(int i=1;i<=m;i++)
        {
            scanf("%s%d",s,&x);
            if(s[0]=='T') Top(x);
            else if(s[0]=='B') Bottom(x);
            else if(s[0]=='I') scanf("%d",&y),Move(x,y);
            else if(s[0]=='A') printf("%d
    ",Ask(x));
            else if(s[0]=='Q') printf("%d
    ",val[Kth(x)]);
        }
        return 0;
    }
  • 相关阅读:
    LintCode "Binary Tree Serialization"
    LeetCode "Find the Duplicate Number"
    LintCode "Route Between Two Nodes in Graph"
    LintCode "Search a 2D Matrix II"
    LintCode "Submatrix Sum"
    LintCode "Sort Letters by Case"
    LeetCode "Peeking Iterator"
    LintCode "Sort Colors II"
    LeetCode "Move Zeroes"
    LintCode "Update Bits"
  • 原文地址:https://www.cnblogs.com/newera/p/9343922.html
Copyright © 2011-2022 走看看