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\n",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("\n");
    }
    return 0;
}

 

posted @ 2013-08-10 21:21  z.arbitrary  阅读(567)  评论(0编辑  收藏  举报