BZOJ1552: [Cerc2007]robotic sort
1552: [Cerc2007]robotic sort
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1428 Solved: 563
[Submit][Status][Discuss]
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
3 4 5 1 6 2
Sample Output
4 6 4 5 6 6
HINT
Source
【题解】
顺便维护一下子树最小值所在splay的节点即可,想知道节点在序列中的位置,把它splay到根看左子树即可
需要离散化让相等的数按出现顺序从小到大排
1 /************************************************************** 2 Problem: 1552 3 User: 33511595 4 Language: C++ 5 Result: Accepted 6 Time:3360 ms 7 Memory:21528 kb 8 ****************************************************************/ 9 10 #include <iostream> 11 #include <cstdio> 12 #include <cstring> 13 #include <cstdlib> 14 #include <algorithm> 15 #include <queue> 16 #include <vector> 17 #include <map> 18 #include <string> 19 #include <cmath> 20 #define min(a, b) ((a) < (b) ? (a) : (b)) 21 #define max(a, b) ((a) > (b) ? (a) : (b)) 22 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 23 template <class T> 24 inline void swap(T& a, T& b) 25 { 26 T tmp = a;a = b;b = tmp; 27 } 28 inline void read(int &x) 29 { 30 x = 0;char ch = getchar(), c = ch; 31 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 32 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 33 if(c == '-') x = -x; 34 } 35 36 const int INF = 0x3f3f3f3f; 37 const int MAXN = 500000 + 10; 38 39 int ch[MAXN][2], fa[MAXN], n, root, size[MAXN], data[MAXN], mi[MAXN], tag[MAXN]; 40 void ddfs(int x) 41 { 42 if(!x) return; 43 ddfs(ch[x][0]); 44 if(x != 1 && x != n + 2) printf("%d ", data[x]); 45 ddfs(ch[x][1]); 46 } 47 int son(int x){return x == ch[fa[x]][1];} 48 void pushup(int rt) 49 { 50 int l = ch[rt][0], r = ch[rt][1]; 51 size[rt] = size[l] + size[r] + 1; 52 if(mi[l] == 0) mi[rt] = mi[r]; 53 else if(mi[r] == 0) mi[rt] = mi[l]; 54 else mi[rt] = data[mi[l]] < data[mi[r]] ? mi[l] : mi[r]; 55 mi[rt] = data[mi[rt]] < data[rt] ? mi[rt] : rt; 56 } 57 void pushdown(int rt) 58 { 59 if(!tag[rt]) return; 60 int l = ch[rt][0], r = ch[rt][1]; 61 tag[l] ^= 1, tag[r] ^= 1; 62 swap(ch[l][0], ch[l][1]), swap(ch[r][0], ch[r][1]); 63 tag[rt] = 0; 64 } 65 void rotate(int x) 66 { 67 int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b]; 68 if(z) ch[z][c] = x; else root = x; fa[x] = z; 69 if(a) fa[a] = y; ch[y][b] = a; 70 ch[x][!b] = y, fa[y] = x; 71 pushup(y), pushup(x); 72 } 73 void dfs(int x) 74 { 75 if(!x) return; 76 dfs(fa[x]); 77 pushdown(x); 78 } 79 void splay(int x, int i) 80 { 81 dfs(x); 82 while(fa[x] != i) 83 { 84 int y = fa[x], z = fa[y]; 85 if(z == i) rotate(x); 86 else 87 if(son(x) == son(y)) rotate(y), rotate(x); 88 else rotate(x), rotate(x); 89 } 90 } 91 int getkth(int rt, int x) 92 { 93 pushdown(rt);int l = ch[rt][0]; 94 if(size[l] + 1 == x) return rt; 95 if(x < size[l] + 1) return getkth(ch[rt][0], x); 96 return getkth(ch[rt][1], x - size[l] - 1); 97 } 98 void turn(int l, int r) 99 { 100 l = getkth(root, l - 1), r = getkth(root, r + 1); 101 // ddfs(root), putchar('\n'); 102 splay(l, 0), splay(r, l); 103 // ddfs(root), putchar('\n'); 104 int now = ch[r][0]; 105 tag[now] ^= 1;swap(ch[now][0], ch[now][1]);pushdown(now); 106 } 107 //查询节点k的排名 108 int getk(int k) 109 { 110 splay(k, 0); 111 return size[ch[k][0]] + 1; 112 } 113 int ask_mi(int l, int r) 114 { 115 l = getkth(root, l - 1), r = getkth(root, r + 1); 116 // ddfs(root), putchar('\n'); 117 splay(l, 0), splay(r, l); 118 // ddfs(root), putchar('\n'); 119 return getk(mi[ch[r][0]]); 120 } 121 122 int cnt[MAXN]; 123 bool cmp(int a, int b) 124 { 125 return data[a] < data[b]; 126 } 127 128 129 int main() 130 { 131 memset(data, 0x3f, sizeof(data)); 132 read(n); 133 for(int i = 2;i <= n + 1;++ i) cnt[i] = i, read(data[i]); 134 std::stable_sort(cnt + 2, cnt + 2 + n, cmp); 135 for(int i = 2;i <= n + 1;++ i) data[cnt[i]] = i; 136 fa[2] = 1, ch[1][1] = 2;size[1] = n + 2;mi[1] = 2; 137 for(int i = 2;i <= n + 1;++ i) 138 { 139 ch[i][1] = i + 1, fa[i + 1] = i;size[i] = n + 3 - i; 140 mi[i] = i; 141 } 142 size[n + 2] = 1;mi[n + 2] = n + 2;root = 1; 143 for(int i = n + 2;i >= 1;-- i) pushup(i); 144 for(int i = 1;i < n;++ i) 145 { 146 int tmp = ask_mi(i + 1, n + 1); 147 printf("%d ", tmp - 1); 148 turn(i + 1, tmp); 149 } 150 int tmp = ask_mi(n + 1, n + 1); 151 printf("%d\n", tmp - 1); 152 return 0; 153 }