[BZOJ1552] [Cerc2007] robotic sort (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

HINT 

Source

  HNOI2009集训Day6

Solution

  预处理$[1, n]$中所有数的位置,每次把当前查找的数$x$旋到根上,其左儿子的子树大小就是答案。再对题意所述的区间加个reverse标记即可。

  因为有区间加标记,所以最好加上头尾两个虚拟节点。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct spaly
 4 {
 5     int c[2], fa, siz, rev;
 6 }a[100005];
 7 pair<int, int> b[100005];
 8  
 9 void push_up(int k)
10 {
11     a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1;
12 }
13  
14 void push_down(int k)
15 {
16     if(a[k].rev)
17     {
18         swap(a[k].c[0], a[k].c[1]), a[k].rev = 0;
19         a[a[k].c[0]].rev ^= 1, a[a[k].c[1]].rev ^= 1;
20     }
21 }
22  
23 void rotate(int &k, int x)
24 {
25     int y = a[x].fa, z = a[y].fa;
26     int dy = a[y].c[1] == x, dz = a[z].c[1] == y;
27     if(k == y) k = x, a[x].fa = z;
28     else a[z].c[dz] = x, a[x].fa = z;
29     a[y].c[dy] = a[x].c[!dy], a[a[x].c[!dy]].fa = y;
30     a[x].c[!dy] = y, a[y].fa = x;
31     push_up(y);
32 }
33  
34 void splay(int &k, int x)
35 {
36     while(k != x)
37     {
38         int y = a[x].fa, z = a[y].fa;
39         push_down(z), push_down(y), push_down(x);
40         if(k != y)
41             if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x);
42             else rotate(k, y);
43         rotate(k, x);
44     }
45     push_up(x);
46 }
47  
48 int find(int k, int x)
49 {
50     if(!k) return 0;
51     push_down(k);
52     if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x);
53     if(x == a[a[k].c[0]].siz + 1) return k;
54     return find(a[k].c[1], x - a[a[k].c[0]].siz - 1);
55 }
56  
57 int main()
58 {
59     int n, root, pos;
60     while(~scanf("%d", &n) && n)
61     {
62         for(int i = 1; i <= n; i++)
63         {
64             scanf("%d", &b[i].first);
65             b[i].second = i + 1;
66         }
67         sort(b + 1, b + n + 1);
68         for(int i = 1; i <= n + 2; i++)
69         {
70             a[i].fa = i + 1, a[i].c[0] = i - 1;
71             a[i].siz = i, a[i].c[1] = a[i].rev = 0;
72         }
73         a[n + 2].fa = 0, root = n + 2;
74         for(int i = 1; i <= n; i++)
75         {
76             splay(root, b[i].second);
77             pos = a[a[root].c[0]].siz;
78             printf("%d", pos);
79             if(i != n) printf(" ");
80             splay(root, find(root, i));
81             splay(a[root].c[1], find(root, pos + 2));
82             a[a[a[root].c[1]].c[0]].rev ^= 1;
83         }
84         puts("");
85     }
86     return 0;
87 }
View Code

   双倍经验的时候到了(。・ω・)ノ゙BZOJ3506 我是雷锋我骄傲。

posted @ 2016-04-21 09:35  CtrlCV  阅读(227)  评论(0编辑  收藏  举报