zoukankan      html  css  js  c++  java
  • hdu3436 splaytree树模拟队列+离散化缩点

    数据较大,需要先把每个top不会操作到的段缩成一个点,记录其开始和结束的位置,和top能操作到的点一起建立一颗伸展树模拟

    然后就是普通的队列模拟操作

    /*
    不会被top操作到的区间就缩点
    通过splay tree模拟出序列,初始序列的第i个缩点对应的树结点也是i
    操作top a:找到结点a,将其移到最左边
    query a:结点a的左边有多少人
    rank a:第a个结点是第几个结点
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define maxn 100005
    #define L ch[r][0]
    #define R ch[r][1]
    using namespace std;
    
    int pre[maxn],ch[maxn][2],size[maxn],num[maxn],root,tot;
    int s[maxn],e[maxn],cnt; 
    void debug();
    inline void newnode(int &r,int fa,int k){
        r=k;
        ch[r][0]=ch[r][1]=0;
        pre[r]=fa;
        size[r]=num[r]=e[k]-s[k]+1;
    }
    inline void pushup(int r){
        size[r]=size[L]+size[R]+num[r];
    }
    void build(int &x,int l,int r,int fa){
        if(l>r) return;
        int mid=l+r>>1;
        newnode(x,fa,mid);
        build(ch[x][0],l,mid-1,x);
        build(ch[x][1],mid+1,r,x);
        pushup(x);
    }
    void init(int n){
        root=tot=0;
        size[root]=pre[root]=ch[root][0]=ch[root][1]=0;
        build(root,1,n,0);
    }
    void Rotate(int x,int kind)
    {
        int y = pre[x];
        //pushdown(y);
        //pushdown(x);//先把y的标记下传,在把x的标记下传
        ch[y][!kind] = ch[x][kind];
        pre[ch[x][kind]] = y;
        if(pre[y])
            ch[pre[y]][ch[pre[y]][1]==y] = x;
        pre[x] = pre[y];
        ch[x][kind] = y;
        pre[y] = x;
        pushup(y);
    }
    //Splay调整,将r结点调整到goal下面
    void splay(int r,int goal)
    {
        //push_down(r);
        while(pre[r] != goal)
        {
            if(pre[pre[r]] == goal)
                Rotate(r,ch[pre[r]][0]==r);
            else
            {
                int y = pre[r];
                int kind = ch[pre[y]][0]==y;
                if(ch[y][kind] == r)
                {
                    Rotate(r,!kind);
                    Rotate(r,kind);
                }
                else
                {
                    Rotate(y,kind);
                    Rotate(r,kind);
                }
            }
        }
        pushup(r);
        if(goal == 0) root = r;
    }  
    int getmin(int r){while(L) r=L;return r;}   
    void del(){
        int t=root;
        if(ch[root][1]){
            root=ch[root][1];
            splay(getmin(root),0);
            ch[root][0]=ch[t][0];
            if(ch[root][0]) pre[ch[root][0]]=root;
        }
        else root=ch[root][0];
        pre[root]=0;
        pushup(root);
    }   
    int Bin(int x){//二分查找x属于那一段
        int l=1,r=cnt;
        while(l<=r){
            int mid=l+r>>1;
            if(s[mid]<=x && e[mid]>=x) return mid;
            if(x<s[mid]) r=mid-1;
            else l=mid+1;
        }
        return -1;
    }void Treavel(int x)
    {
        if(x)
        {
            Treavel(ch[x][0]);
            printf("结点:%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d  num = %2d s = %2d e = %2d
    ",x,ch[x][0],ch[x][1],pre[x],size[x],num[x],s[x],e[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug()
    {
        printf("root:%d
    ",root);
        Treavel(root);
    }
    void top(int x){//把结点r移到最左边
        int r=Bin(x);
        splay(r,0);
        del();
       
        ch[r][0]=0;
        ch[r][1]=root;
        pre[root]=r;
        root=r;
        pre[root]=0;
        pushup(root);
        //debug();
    }
    int query(int x){//结点x左边有多少结点
        int r=Bin(x);
        splay(r,0);
        return size[ch[root][0]]+x-s[r]+1;
    }
    int rankk(int r,int k){//排在第k位的结点
        int t=size[ch[r][0]];
        if(k<=t) return rankk(ch[r][0],k);
        else if(k<=t+num[r]) return s[r]+k-t-1;
        else return rankk(ch[r][1],k-t-num[r]);
    }
    
    char op[maxn][10];
    int qnum[maxn],p[maxn];
    
    int main(){
        int n,q,T;
        scanf("%d",&T);
        for(int tt=1;tt<=T;tt++){
            scanf("%d%d",&n,&q);
            int t=0;
            for(int i=0;i<q;i++){
                scanf("%s%d",op[i],&qnum[i]);
                if(op[i][0]=='T')
                    p[t++]=qnum[i];
            }
            p[t++]=1;
            p[t++]=n;
            sort(p,p+t);
            t=unique(p,p+t)-p;
            cnt=0;
            for(int i=0;i<t;i++){
                if(i>0 && p[i]-p[i-1]>1){
                    cnt++;
                    s[cnt]=p[i-1]+1;
                    e[cnt]=p[i]-1;
                }
                cnt++;
                s[cnt]=p[i];e[cnt]=p[i];
            }
            init(cnt);
          //  debug();
            printf("Case %d:
    ",tt);
            for(int i=0;i<q;i++){
            //    debug();
                if(op[i][0]=='T') top(qnum[i]);
                else if(op[i][0]=='Q') printf("%d
    ",query(qnum[i]));
                else printf("%d
    ",rankk(root,qnum[i]));
               // debug();
            }
        }
        return 0;
    }
  • 相关阅读:
    ETL之Kettle
    java 之webmagic 网络爬虫
    【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解
    【AC自动机】【字符串】【字典树】AC自动机 学习笔记
    【前缀和】【two-pointer】【贪心】洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector 题解
    【KMP】【矩阵加速】【递推】洛谷 P3193 [HNOI2008]GT考试 题解
    【KMP】洛谷P2375 [NOI2014]动物园 题解
    【KMP】【字符串】KMP字符串匹配算法 学习笔记
    【DP】+【贪心】【前缀和】洛谷P2893 [USACO08FEB]修路Making the Grade 题解
    【字典树】【树】【二进制】bzoj1954/POJ3764The xor-longest Path 题解
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10006172.html
Copyright © 2011-2022 走看看