[CQOI2014]排序机械臂

Description

这里写图片描述

Solution

 一道很水很水的题,splay树保存一个最小值,每次查找最小值所在的位置,旋转到根,输出它在第几位。然后将它之前的节点打上翻转标记,维护一下即可。

注意这道题要先排序,因为翻转操作之后就不知到它原来的位置了。

  1 //Never forget why you start
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<algorithm>
  8 #define ll(x) bst[x].child[0]
  9 #define rr(x) bst[x].child[1]
 10 #define son(x,t) bst[x].child[t]
 11 #define inf (2147483647)
 12 using namespace std;
 13 int root,n,cnt;
 14 struct point{
 15   int x,id;
 16 }a[100005];
 17 bool cmp1(const point a,const point b){
 18   return a.x<b.x||(a.x==b.x&&a.id<b.id);
 19 }
 20 bool cmp2(const point a,const point b){
 21   return a.id<b.id;
 22 }
 23 struct BST{
 24   int child[2],fa,mmin,x,size,lazy;
 25 }bst[100005];
 26 void push_up(int root){
 27   int l=ll(root),r=rr(root);
 28   bst[root].mmin=bst[root].x;
 29   if(l)bst[root].mmin=min(bst[root].mmin,bst[l].mmin);
 30   if(r)bst[root].mmin=min(bst[root].mmin,bst[r].mmin);
 31   bst[root].size=bst[l].size+bst[r].size+1;
 32 }
 33 void push_down(int root){
 34   int l=ll(root),r=rr(root);
 35   if(bst[root].lazy){
 36     if(l)bst[l].lazy^=1;
 37     if(r)bst[r].lazy^=1;
 38     bst[root].lazy^=1;
 39     swap(ll(root),rr(root));
 40   }
 41 }
 42 void rotate(int r,int t){
 43   int fa=bst[r].fa;
 44   son(fa,!t)=son(r,t);bst[son(r,t)].fa=fa;
 45   son(bst[fa].fa,son(bst[fa].fa,1)==fa)=r;bst[r].fa=bst[fa].fa;
 46   son(r,t)=fa;bst[fa].fa=r;
 47   push_up(fa);
 48   push_up(r);
 49 }
 50 void splay(int r,int goal){
 51   int fa=bst[r].fa;
 52   while(fa!=goal){
 53     if(bst[fa].fa==goal)rotate(r,son(fa,0)==r);
 54     else{
 55       int t=son(bst[fa].fa,0)==fa;
 56       if(son(fa,t)==r)rotate(r,!t),rotate(r,t);
 57       else rotate(fa,t),rotate(r,t);
 58     }
 59     fa=bst[r].fa;
 60   }
 61   if(goal==0)root=r;
 62 }
 63 int search(int root){
 64   push_down(root);
 65   if(bst[root].mmin==bst[ll(root)].mmin)return search(ll(root));
 66   if(bst[root].mmin==bst[root].x)return root;
 67   if(bst[root].mmin==bst[rr(root)].mmin)return search(rr(root)); 
 68 }
 69 int find(int root,int k){
 70   push_down(root);
 71   int y=bst[ll(root)].size;
 72   if(y+1==k)return root;
 73   else if(y>=k)return find(ll(root),k);
 74   else return find(rr(root),k-y-1);
 75 }
 76 void build(int &root,int left,int right,int fa){
 77   int mid=(left+right)>>1;
 78   root=++cnt;
 79   bst[root].fa=fa;
 80   if(left==right){
 81     bst[root].x=bst[root].mmin=a[left].x;
 82     bst[root].size=1;
 83     return;
 84   }
 85   if(left<mid)build(ll(root),left,mid-1,root);
 86   if(mid<right)build(rr(root),mid+1,right,root);
 87   bst[root].x=a[mid].x;bst[root].size=1;
 88   push_up(root);
 89 }
 90 int split(int l,int r){
 91   l--;r++;
 92   int x=find(root,l),y=find(root,r);
 93   splay(x,0);
 94   splay(y,x);
 95   return ll(y);
 96 }
 97 void delet(int pos){
 98   splay(pos,0);
 99   int x=find(root,bst[ll(pos)].size);
100   int y=find(root,bst[ll(pos)].size+2);
101   splay(x,0);
102   splay(y,x);
103   son(y,0)=0;
104   bst[pos].fa=0;
105   push_up(y);
106   push_up(x);
107 }
108 int main(){
109   int i,j;
110   scanf("%d",&n);
111   for(i=1;i<=n;i++)
112     scanf("%d",&a[i+1].x),a[i+1].id=i;
113   sort(a+2,a+n+2,cmp1);
114   for(i=1;i<=n;i++)
115     a[i+1].x=i;
116   sort(a+2,a+n+2,cmp2);
117   n+=2;
118   a[1].x=a[n].x=inf;
119   bst[0].x=bst[0].mmin=inf;
120   bst[0].size=0;
121   build(root,1,n,0);
122   for(i=0;i<=n-3;i++){
123     int x=split(2,n-1-i);
124     x=search(x);
125     splay(find(root,1),0);
126     splay(x,root);
127     bst[ll(x)].lazy^=1;
128     printf("%d ",bst[ll(x)].size+1+i);
129     delet(x);
130   }
131   return 0;
132 }

 

posted @ 2018-01-11 15:58  kakakakakaka  阅读(220)  评论(0编辑  收藏  举报

Never forget why you start

//鼠标爆炸特效