链接:http://cogs.pro/cogs/problem/problem.php?pid=1545
题意:一个机器每次只会将一个区间反转使右端点的物品正确到达左端点,求出每次转移的右端点。
维护一个splay,每次操作,把哨兵转到根,右端点后一个到达右儿子,该节点到达这个右儿子的左儿子,标记完成后再转到左子树,扔掉该节点。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int SIZEN=100010,INF=0x7fffffff/2; 6 class SPLAYTREE{ 7 public: 8 class NODE{ 9 public: 10 int key,size; 11 bool rev; 12 NODE *f,*lc,*rc; 13 int mx; 14 NODE(int k){key=mx=k;size=1;rev=0;} 15 }*Nil,*Root,*left,*right; 16 NODE *newNODE(int key){ 17 NODE *T=new NODE(key); 18 T->lc=T->rc=T->f=Nil; 19 return T; 20 } 21 void clear(){ 22 Nil=new NODE(INF); 23 Nil->lc=Nil->rc=Nil->f=Nil; 24 Nil->size=0; 25 left=newNODE(INF),right=newNODE(INF); 26 left->size++,left->rc=right,right->f=left; 27 Root=left; 28 } 29 void pushdown(NODE *T){ 30 if(T->rev){ 31 T->lc->rev^=1,T->rc->rev^=1; 32 swap(T->lc,T->rc); 33 T->rev=0; 34 } 35 } 36 void update(NODE *T){ 37 T->size=T->lc->size+T->rc->size+1; 38 T->mx=min(T->lc->mx,T->rc->mx); 39 T->mx=min(T->mx,T->key); 40 } 41 void zig(NODE *T){ 42 NODE *P=T->f,*rson=T->rc; 43 pushdown(P->rc),pushdown(T->lc),pushdown(T->rc); 44 if(Root==P) Root=T; 45 else (P->f->lc==P)?(P->f->lc=T):(P->f->rc=T); 46 T->f=P->f,P->f=T;rson->f=P;T->rc=P;P->lc=rson; 47 update(P); 48 } 49 void zag(NODE *T){ 50 NODE *P=T->f,*lson=T->lc; 51 pushdown(P->lc),pushdown(T->lc),pushdown(T->rc); 52 if(Root==P) Root=T; 53 else (P->f->lc==P)?(P->f->lc=T):(P->f->rc=T); 54 T->f=P->f,P->f=T;lson->f=P;T->lc=P;P->rc=lson; 55 update(P); 56 } 57 void splay(NODE *ANC,NODE *t){ 58 pushdown(t); 59 if(t==ANC){update(t);return;} 60 bool reach=false; 61 while(!reach){ 62 NODE *P=t->f; 63 if(P==ANC) (P->lc==t)?zig(t):zag(t),reach=true; 64 else{ 65 if(P->f==ANC) reach=true; 66 if(P->f->lc==P) (P->lc==t)?zig(P):zag(t),zig(t); 67 else (P->rc==t)?zag(P):zig(t),zag(t); 68 } 69 } 70 update(t); 71 } 72 void insert(int *a,int k){ 73 NODE *t=newNODE(a[1]),*p=t,*q=t; 74 for(int i=2;i<=k;i++) t=newNODE(a[i]),t->f=p,p->rc=t,p=t; 75 Root->rc->lc=q,q->f=Root->rc; 76 splay(Root,p); 77 } 78 void select(NODE *ANC,int k){ 79 NODE *t=ANC; 80 while(true){ 81 pushdown(t); 82 if(k==t->lc->size+1){ 83 splay(ANC,t); 84 return; 85 } 86 if(k<=t->lc->size) t=t->lc; 87 else k-=t->lc->size+1,t=t->rc; 88 } 89 } 90 void findmin(int k){ 91 NODE *t=Root; 92 int pos=0; 93 while(t->key!=t->mx){ 94 pushdown(t); 95 if(t->lc->mx==t->mx) t=t->lc; 96 else pos+=t->lc->size+1,t=t->rc; 97 } 98 pushdown(t); 99 pos+=t->lc->size; 100 printf("%d ",pos+k-1); 101 select(Root,1); 102 select(Root->rc,pos+1); 103 select(Root->rc->lc,pos); 104 Root->rc->lc->rev^=1; 105 pushdown(Root->rc->lc); 106 select(Root->rc,2); 107 delete Root->rc->lc; 108 Root->rc->lc=Nil; 109 splay(Root,Root->rc); 110 } 111 }tree; 112 int N; 113 pair<int,int> height[SIZEN]; 114 int equh[SIZEN]={0}; 115 bool work(void){ 116 scanf("%d",&N); 117 if(!N) return false; 118 for(int i=1;i<=N;i++) scanf("%d",&height[i].first),height[i].second=i; 119 sort(height+1,height+1+N); 120 for(int i=1;i<=N;i++) equh[height[i].second]=i; 121 tree.clear(); 122 tree.insert(equh,N); 123 for(int i=1;i<=N;i++) tree.findmin(i); 124 puts(""); 125 return true; 126 } 127 int main(){ 128 freopen("roboticsort.in","r",stdin); 129 freopen("roboticsort.out","w",stdout); 130 while(work()); 131 return 0; 132 }