• hdu-1890-Robotic Sort splay区间翻转


    题意:

    依次找第i大的数下标pos[i],然后将区间[i,pos[i]]翻转

    分析:

    splay树区间翻转

    // File Name: ACM/HDU/1890.cpp
    // Author: Zlbing
    // Created Time: 2013年08月10日 星期六 20时26分39秒
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    #define L ch[x][0]  
    #define R ch[x][1]  
    #define KT (ch[ ch[rt][1] ][0])  
    const int MAXN = 100010;  
    int cmp(pair<int,int> a,pair<int,int> b){  
            if(a.first!=b.first) return a.first<b.first;  
            return a.second < b.second;  
    }  
    int mp[MAXN];
    int id[MAXN];
    pair<int,int> num[MAXN];
    struct SplayTree {  
        int sz[MAXN];  
        int ch[MAXN][2];  
        int pre[MAXN];  
        int rt,top;  
        inline void down(int x){  
            if(flip[x]) {  
                flip[ L ] ^= 1;  
                flip[ R ] ^= 1;  
                swap(L,R);  
                flip[x]=0;  
            }  
        }  
        inline void up(int x){  
            sz[x]=1+sz[ L ] + sz[ R ];  
        }  
        inline void Rotate(int x,int f){  
            int y=pre[x];  
            down(y);  
            down(x);  
            ch[y][!f] = ch[x][f];  
            pre[ ch[x][f] ] = y;  
            pre[x] = pre[y];  
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;  
            ch[x][f] = y;  
            pre[y] = x;  
            up(y);  
        }  
        inline void Splay(int x,int goal){//将x旋转到goal的下面  
            down(x);//防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了  
            while(pre[x] != goal){  
                down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变  
                if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][0] == x);  
                else   {  
                    int y=pre[x],z=pre[y];  
                    int f = (ch[z][0]==y);  
                    if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);  
                    else Rotate(y,f),Rotate(x,f);  
                }  
            }  
            up(x);  
            if(goal==0) rt=x;  
        }  
        inline void RTO(int k,int goal){//将第k位数旋转到goal的下面  
            int x=rt;  
            down(x);  
            while(sz[ L ]+1 != k) {  
                if(k < sz[ L ] + 1 ) x=L;  
                else {  
                    k-=(sz[ L ]+1);  
                    x = R;  
                }  
                down(x);  
            }  
            Splay(x,goal);  
        }  
        void vist(int x){  
            if(x){  
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   %2d  flip:%d
    ",x,L,R,val[x],flip[x]);  
                vist(L);  
                vist(R);  
            }  
        }  
        void Newnode(int &x,int c,int f){  
            x=++top;flip[x]=0;  
            L = R = 0;  pre[x] = f;  
            sz[x]=1; val[x]=c;  
        }  
        inline void build(int &x,int l,int r,int f){  
            if(l>r) return ;  
            int m=(l+r)>>1;  
            Newnode(x,num[id[m]].first,f);  
            mp[id[m]]=x;  
            build(L , l , m-1 , x);  
            build(R , m+1 , r , x);  
            pre[x]=f;  
            up(x);  
        }  
          
        inline void init(){  
            ch[0][0]=ch[0][1]=pre[0]=sz[0]=0;  
            rt=top=0; flip[0]=0; val[0]=0;  
        }  
        void Del(){  
             int t=rt;  
             if(ch[rt][1]) {  
                 rt=ch[rt][1];  
                 RTO(1,0);  
                 ch[rt][0]=ch[t][0];  
                 if(ch[rt][0]) pre[ch[rt][0]]=rt;  
             }  
             else rt=ch[rt][0];  
             pre[rt]=0;  
             up(rt);  
        }  
        int flip[MAXN];  
        int val[MAXN];  
    }spt;  
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            if(!n)break;
            spt.init();
            REP(i,1,n)
            {
                scanf("%d",&num[i].first);
                num[i].second=i;
            }
            sort(num+1,num+n+1,cmp);
            REP(i,1,n)
                id[num[i].second]=i;
            spt.build(spt.rt,1,n,0);
    
            REP(i,1,n)
            {
                spt.Splay(mp[i],0);
                int ans=i+spt.sz[spt.ch[spt.rt][0]];
                spt.flip[spt.ch[spt.rt][0]]^=1;
                spt.Del();
                if(i==1)printf("%d",ans);
                else printf(" %d",ans);
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    Cisco 交换机配置的基本命令
    Mysql读写分离方案-Amoeba环境部署记录
    centos7下部署zabbix3.4+grafana
    Docker
    Linux 安装源码软件
    mysql 日志
    mysql导出导入数据
    mysql 数据库的备份和还原
    Mysql 数据库管理
    英语单词
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3250715.html
Copyright © 2020-2023  润新知