bzoj1552/3506[Cerc2007]robotic sort splay翻转,区间最值

Posted Kaiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1552/3506[Cerc2007]robotic sort splay翻转,区间最值相关的知识,希望对你有一定的参考价值。

【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翻转,区间最值的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1552: [Cerc2007]robotic sort.

BZOJ1552: [Cerc2007]robotic sort

[BZOJ1552][Cerc2007]robotic sort

bzoj1552 [Cerc2007]robotic sort

bzoj1552 [Cerc2007]robotic sort

[bzoj1552][Cerc2007]robotic sort&&[bzoj3506][Cqoi2014]排序机械臂