• 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;
    }
  • 相关阅读:
    shell脚本 加密备份MySQL数据库
    C#在Linux下获取文件夹信息(所在磁盘总大小,使用空间,已用空间,使用率)
    bootstrap--- 两种bootstrap multiselect组件大比拼
    C# 文件重命名
    C#中一些常用的正则表达式
    C# 文件压缩加解密
    Python 由__dict__和dir()引发的一些思考
    python3随机生成中文字符
    Django自定义过滤器中is_safe和need_autoescape两个参数的理解
    Python格式化字符串--format
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10006172.html
Copyright © 2020-2023  润新知