题目大意:
一个长度为$n(nleq10000)$的序列按照如下方式进行$n$次调整实现排序,每次在无序区域找出最小数的位置$p$,翻转区间$[i,j]$,此后区间$[1,i]$为有序。求每次操作$p$的值。
思路:
Splay维护区间。首先初始顺序为结点编号建立Splay,然后按照高度排序,求出每次操作的结点编号。每次询问时将询问点提到根,则$size[ch[root][0]]+1$即为所求的答案,翻转可以通过区间标记实现。
1 #include<cstdio> 2 #include<cctype> 3 #include<climits> 4 #include<algorithm> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int N=100003; 13 int v[N],s[N]; 14 class SplayTree { 15 private: 16 int val[N],size[N],par[N],ch[N][2],root; 17 bool rev[N]; 18 void push_down(const int &p) { 19 if(!rev[p]) return; 20 rev[ch[p][0]]^=1; 21 rev[ch[p][1]]^=1; 22 std::swap(ch[p][0],ch[p][1]); 23 rev[p]=0; 24 } 25 void push_up(const int &p) { 26 size[p]=size[ch[p][0]]+size[ch[p][1]]+1; 27 } 28 void rotate(const int &x) { 29 const int y=par[x],z=par[y]; 30 push_down(y),push_down(x); 31 const int b=x==ch[y][0]; 32 par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x; 33 par[ch[z][ch[z][1]==y]=x]=z; 34 push_up(y),push_up(x); 35 } 36 void splay(int x,const int &goal) { 37 for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) { 38 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y); 39 } 40 if(!goal) root=x; 41 } 42 int find(int x) { 43 for(register int y=root;;y=ch[y][size[ch[y][0]]+1<x]) { 44 push_down(y); 45 if(par[y]&&y==ch[par[y]][1]) x-=size[ch[par[y]][0]]+1; 46 if(size[ch[y][0]]+1==x) return y; 47 } 48 } 49 public: 50 void build(const int &n) { 51 for(register int i=1;i<=n+2;i++) { 52 par[ch[i-1][1]=i]=i-1; 53 val[i]=v[i]; 54 } 55 size[n+2]=1; 56 splay(n+2,0); 57 } 58 int query(const int &x) { 59 splay(s[x],0); 60 const int ret=size[ch[s[x]][0]]; 61 splay(find(x-1),0); 62 splay(find(ret+2),root); 63 rev[ch[ch[root][1]][0]]^=1; 64 return ret; 65 } 66 }; 67 SplayTree t; 68 inline bool cmp(const int &a,const int &b) { 69 return v[a]==v[b]?a<b:v[a]<v[b]; 70 } 71 int main() { 72 const int n=getint(); 73 for(register int i=2;i<=n+1;i++) { 74 v[i]=getint(); 75 s[i]=i; 76 } 77 t.build(n); 78 std::sort(&s[2],&s[n+1]+1,cmp); 79 v[1]=INT_MIN; 80 v[n+2]=INT_MAX; 81 for(register int i=2;i<=n+1;i++) { 82 printf("%d%c",t.query(i)," "[i==n+1]); 83 } 84 return 0; 85 }