zoukankan      html  css  js  c++  java
  • ZJOI2006 书架

    传送门

    这道题与普通的(splay)不大相同,别的都是以权值来排序,但这道题是以位置进行排序的,也就是对于一个节点,它的左子树中的节点都在它的上面,右子树中的节点都在他的下面。

    这个比较独特的一点在于建树,这次不能再二分查找要插入的位置了,而是每一次直接把当前插入的点作为上一次插入的点的右儿子(符合上面说的性质),然后(splay)一下就好了。

    至于置顶和置底操作,实际上就相当于把它的左/右子树合并到它的后继/前驱上,这个还是很简单的。

    放书操作的话就是找到前驱和后继然后直接交换它们的值。

    (ask)操作就把要找的那个点(splay)到根之后输出其左子树大小,求排名的话就像(BST)一样了。

    注意因为本题平衡树是以位置来排序,但是我们在找的时候不能通过(BST)的方法找到,所以我们还记录一下(pos_i)表示位置为(i)的书在树上的编号。(这个在执行过插入操作之后就不会变了),这样就可以了。

    一直没(debug)出来竟然是因为多打了一个按位异或……

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define de putchar('#')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 10000005;
    const int INF = 1000000009;
     
    int read()
    {
       int ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9')
       {
          if(ch == '-') op = -1;
          ch = getchar();
       }
       while(ch >='0' && ch <= '9')
       {
          ans *= 10;
          ans += ch - '0';
          ch = getchar();
       }
       return ans * op;
    }
    
    struct node
    {
       int fa,ch[2],son,cnt,val;
    }t[M<<1];
    
    int n,m,idx,tot,x,pos[M<<1],root,a;
    char s[10];
    
    bool get(int x)
    {
       return t[t[x].fa].ch[1] == x;
    }
    
    void pushup(int x)
    {
       t[x].son = t[t[x].ch[0]].son + t[t[x].ch[1]].son + t[x].cnt;
    }
    
    void rotate(int x)
    {
       int y = t[x].fa,z = t[y].fa,k = get(x);
       t[z].ch[t[z].ch[1] == y] = x,t[x].fa = z;
       t[y].ch[k] = t[x].ch[k^1],t[t[y].ch[k]].fa = y;
       t[x].ch[k^1] = y,t[y].fa = x;
       pushup(x),pushup(y);
    }
    
    void splay(int x,int goal)
    {
       while(t[x].fa != goal)
       {
          int y = t[x].fa,z = t[y].fa;
          if(z != goal) (t[y].ch[1] == x) ^ (t[z].ch[1] == y) ? rotate(x) : rotate(y);
          rotate(x);
       }
       if(!goal) root = x;
       //pos[t[x].val] = x;
    }
    
    void insert(int x)
    {
       int u = ++idx;
       t[u].val = x,pos[x] = u;
       t[u].son = t[u].cnt = 1;
       t[u].ch[0] = t[u].ch[1] = 0;
       if(u > 1) t[u-1].ch[1] = u,t[u].fa = u-1,splay(u,0);
    }
    
    void change(int x,int p)
    {
       splay(pos[x],0);
       if(!t[root].ch[p]) return;
       if(!t[root].ch[p^1]) t[root].ch[p^1] = t[root].ch[p],t[root].ch[p] = 0;
       else
       {
          int g = t[root].ch[p^1];
          while(t[g].ch[p]) g = t[g].ch[p];
          t[t[root].ch[p]].fa = g,t[g].ch[p] = t[root].ch[p],t[root].ch[p] = 0;
          splay(t[g].ch[p],0);
       }
    }
    
    void modify(int x,int f)
    {
       splay(pos[x],0);
       if(f == 0) return;
       else if(f == 1)
       {
          int g = t[root].ch[1],p = pos[x];
          while(t[g].ch[0]) g = t[g].ch[0];
          swap(pos[x],pos[t[g].val]);
          swap(t[p].val,t[g].val);
       }
       else if(f == -1)
       {
          int g = t[root].ch[0],p = pos[x];
          while(t[g].ch[1]) g = t[g].ch[1];
          swap(pos[x],pos[t[g].val]);
          swap(t[p].val,t[g].val);
       }
    }
    
    void ask(int x)
    {
       splay(pos[x],0);
       printf("%d
    ",t[t[root].ch[0]].son);
    }
    
    int rk(int x)
    {
       int u = root;
       while(1)
       {
          int y = t[u].ch[0];
          if(x <= t[y].son) u = y;
          else if(x > t[y].son + t[u].cnt) x -= (t[y].son + t[u].cnt),u = t[u].ch[1];
          else return t[u].val;
       }
    }
    
    int main()
    {
       //pos[0] = t[0].son = t[0].cnt = t[0].ch[1] = t[0].ch[0] = t[0].fa = t[0].val = 0;
       n = read(),m = read();
       rep(i,1,n) x = read(),insert(x);
       rep(i,1,m)
       {
          scanf("%s",s);
          if(s[0] == 'T') x = read(),change(x,0);
          else if(s[0] == 'B') x = read(),change(x,1);
          else if(s[0] == 'I') x = read(),a = read(),modify(x,a);
          else if(s[0] == 'A') x = read(),ask(x);
          else if(s[0] == 'Q') x = read(),printf("%d
    ",rk(x));
       }
       return 0;
    }
    
    
  • 相关阅读:
    poj 3280 Cheapest Palindrome (dp)
    hdu 4359 Easy Tree DP? ( dp )
    hdu 2844 Coins (多重背包+ 二进制优化)
    三分法 讲解
    poj 1191 棋盘分割 (dp)
    hdu 4340 Capturing a country(树形 dp) (2012 MultiUniversity Training Contest 5 )
    子类和父类的构造函数
    CreateProcess执行一个控制台程序,隐藏DOS窗口
    单个字符比较
    MFC 程序入口和执行流程
  • 原文地址:https://www.cnblogs.com/captain1/p/10094808.html
Copyright © 2011-2022 走看看