题意:
依次找第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; }