1552/3506. [CQOI2014]排序机械臂【平衡树-splay】

Description

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,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
 
记录下每个装置对应位置然后依次splay翻转区间即可。
 
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #define N (100000+100)
  6 using namespace std;
  7 struct node
  8 {
  9     int id,num;
 10 } b[N];
 11 int Key[N],Rev[N],Size[N];
 12 int Father[N],Son[N][2];
 13 int n,Root,a[N],Rank[N];
 14 
 15 bool cmp(node a,node b)
 16 {
 17     return a.num==b.num?a.id<b.id:a.num<b.num;
 18 }
 19 inline int Get(int x)
 20 {
 21     return Son[Father[x]][1]==x;
 22 }
 23 
 24 inline void Update(int x)
 25 {
 26     Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
 27 }
 28 
 29 inline void Pushdown(int x)
 30 {
 31     if (Rev[x])
 32     {
 33         Rev[x]=0;
 34         swap(Son[x][0],Son[x][1]);
 35         Rev[Son[x][0]]^=1;
 36         Rev[Son[x][1]]^=1;    
 37     }
 38 }
 39 
 40 inline void Rotate(int x)
 41 {
 42     Pushdown(Father[x]);
 43     Pushdown(x);
 44     int wh=Get(x);
 45     int fa=Father[x],fafa=Father[fa];
 46     Son[fa][wh]=Son[x][wh^1];
 47     Father[fa]=x;
 48     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
 49     Son[x][wh^1]=fa;
 50     Father[x]=fafa;
 51     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
 52     Update(fa);
 53     Update(x);
 54 }
 55 
 56 inline void Splay(int x,int tar)
 57 {
 58     for (int fa;(fa=Father[x])!=tar;Rotate(x))
 59         if (Father[fa]!=tar)
 60             Rotate(Get(fa)==Get(x)?fa:x);
 61     if (!tar) Root=x;
 62 }
 63 
 64 void Build(int l,int r,int fa)
 65 {
 66     if (l>r) return;
 67     if (l==r)
 68     {
 69         Size[l]=1;
 70         Father[l]=fa;
 71         Son[fa][l>fa]=l;
 72         return;
 73     }
 74     int mid=(l+r)>>1;
 75     Build(l,mid-1,mid);
 76     Build(mid+1,r,mid);
 77     Father[mid]=fa;
 78     Son[fa][mid>fa]=mid;
 79     Update(mid);
 80 }
 81 
 82 int Findx(int x)
 83 {
 84     int now=Root;
 85     while (1)
 86     {
 87         Pushdown(now);
 88         if (Size[Son[now][0]]>=x)
 89             now=Son[now][0];
 90         else
 91         {
 92             x-=Size[Son[now][0]];
 93             if (x==1)
 94             {
 95                 Splay(now,0);
 96                 return now;
 97             }
 98             x--;
 99             now=Son[now][1];
100         }
101     }
102 }
103 
104 inline int Split(int x,int y)
105 {
106     int xx=Findx(x),yy=Findx(y);
107     Splay(xx,0);
108     Splay(yy,xx);
109     return Son[yy][0];
110 }
111 
112 int main()
113 {
114     scanf("%d",&n);
115     for (int i=1; i<=n; ++i)
116     {
117         scanf("%d",&a[i+1]);
118         b[i].id=i+1;
119         b[i].num=a[i+1];
120     }
121     sort(b+1,b+n+1,cmp);
122     for (int i=1; i<=n; ++i)
123         Rank[i]=b[i].id;
124     Build(1,n+2,0);
125     Root=(n+3)/2;
126     for (int i=1; i<=n; ++i)
127     {
128         Splay(Rank[i],0);
129         int ans=Size[Son[Root][0]]+1;
130         printf("%d ",ans-1);
131         int hh=Split(i,ans+1);
132         Rev[hh]^=1;
133     }
134 }
posted @ 2018-03-30 23:09  Refun  阅读(174)  评论(0编辑  收藏  举报