1. 程式人生 > >【bzoj1552/3506】[Cerc2007]robotic sort splay翻轉,區間最值

【bzoj1552/3506】[Cerc2007]robotic sort splay翻轉,區間最值

geo ges 空格 操作 i++ led border 輸出 print

【bzoj1552/3506】[Cerc2007]robotic sort

Description

技術分享圖片

Input

輸入共兩行,第一行為一個整數N,N表示物品的個數,1<=N<=100000。第二行為N個用空格隔開的正整數,表示N個物品最初排列的編號。

Output

輸出共一行,N個用空格隔開的正整數P1,P2,P3…Pn,(1 < = Pi < = N),Pi表示第i次操作前第i小的物品所在的位置。 註意:如果第i次操作前,第i小的物品己經在正確的位置Pi上,我們將區間[Pi,Pi]反轉(單個物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6 題解:裸題
  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6 
  7 #define inf 1000000007
  8 #define N 100007
  9 #define ls c[p][0]
 10 #define rs c[p][1]
 11 using namespace
std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(ch>9||ch<0){if (ch==-) f=-1;ch=getchar();} 16 while(ch<=9&&ch>=0){x=(x<<3)+(x<<1)+ch-0;ch=getchar();} 17 return x*f; 18 } 19 20 int n,rt; 21 int a[N],rev[N],mi[N],flag[N],fa[N],sz[N],c[N][2
],val[N],s[N]; 22 23 void update(int p) 24 { 25 sz[p]=sz[ls]+sz[rs]+1; 26 mi[p]=val[p],flag[p]=p; 27 if ((mi[ls]<mi[p])||(mi[ls]==mi[p]&&flag[p]>flag[ls])) mi[p]=mi[ls],flag[p]=flag[ls]; 28 if ((mi[rs]<mi[p])||(mi[rs]==mi[p]&&flag[p]>flag[rs])) mi[p]=mi[rs],flag[p]=flag[rs]; 29 } 30 void pushdown(int p) 31 { 32 if (rev[p]) 33 { 34 rev[p]^=1,rev[ls]^=1,rev[rs]^=1; 35 swap(c[p][0],c[p][1]); 36 } 37 } 38 void build(int l,int r,int f) 39 { 40 if (l>r) return; 41 if (l==r) 42 { 43 val[l]=a[l],sz[l]=1,fa[l]=f,mi[l]=a[l],flag[l]=l; 44 if (l<f) c[f][0]=l; 45 else c[f][1]=l; 46 return; 47 } 48 int mid=(l+r)>>1; 49 build(l,mid-1,mid),build(mid+1,r,mid); 50 if (mid<f) c[f][0]=mid; 51 else c[f][1]=mid; 52 fa[mid]=f,val[mid]=a[mid],mi[mid]=a[mid],flag[mid]=mid; 53 update(mid); 54 } 55 void rotate(int x,int &k) 56 { 57 int y=fa[x],z=fa[y],l,r; 58 if (c[y][0]==x) l=0;else l=1;r=l^1; 59 if (y==k) k=x;//交換後x就等於y 60 else if (c[z][0]==y) c[z][0]=x; 61 else c[z][1]=x; 62 fa[x]=z,fa[y]=x,fa[c[x][r]]=y; 63 c[y][l]=c[x][r],c[x][r]=y; 64 update(y),update(x); 65 } 66 void splay(int x,int &k) 67 { 68 int top=0;s[++top]=x; 69 for(int i=x;fa[i];i=fa[i]) 70 s[++top]=fa[i]; 71 for(int i=top;i;i--) 72 if(rev[s[i]])pushdown(s[i]); 73 while(x!=k) 74 { 75 int y=fa[x],z=fa[y]; 76 if (y!=k) 77 { 78 if (c[y][0]==x^c[z][0]==y) rotate(x,k); 79 else rotate(y,k); 80 } 81 rotate(x,k); 82 } 83 } 84 int find(int p,int num) 85 { 86 pushdown(p); 87 if (sz[ls]>=num) return find(ls,num); 88 else if (sz[ls]+1==num) return p; 89 else return find(rs,num-sz[ls]-1); 90 } 91 int query(int l,int r) 92 { 93 int x=find(rt,l),y=find(rt,r+2); 94 splay(x,rt),splay(y,c[x][1]); 95 int now=c[y][0]; 96 return flag[now]; 97 } 98 void spin(int l,int r) 99 { 100 int x=find(rt,l),y=find(rt,r+2); 101 splay(x,rt),splay(y,c[x][1]); 102 int now=c[c[x][1]][0]; 103 rev[now]^=1; 104 } 105 int main() 106 { 107 freopen("fzy.in","r",stdin); 108 freopen("fzy.out","w",stdout); 109 110 int n=read(); 111 for (int i=2;i<=n+1;i++) 112 a[i]=read(); 113 a[1]=a[n+2]=a[0]=inf,mi[0]=inf; 114 build(1,n+2,0),rt=(1+n+2)>>1; 115 for (int i=1;i<=n;i++) 116 { 117 int wei=query(i,n); 118 splay(wei,rt); 119 if (i!=n) printf("%d ",sz[c[wei][0]]); 120 else printf("%d",sz[c[wei][0]]); 121 spin(i,sz[c[wei][0]]); 122 } 123 }

【bzoj1552/3506】[Cerc2007]robotic sort splay翻轉,區間最值