1. 程式人生 > >bzoj 3506[Cqoi2014]排序機械臂 - splay

bzoj 3506[Cqoi2014]排序機械臂 - splay

getch pri 排名 getchar pushd ast for clu 序列

        3506: [Cqoi2014]排序機械臂

題目描述

為了把工廠中高低不等的物品按從低到高排好序,工程師發明了一種排序機械臂。它遵循一個簡單的排序規則,第一次操作找到高度最低的物品的位置 P_1P1? ,並把左起第一個物品至 P_1P1? 間的物品 (即區間 [1,P_1][1,P1?] 間的物品) 反序;第二次找到第二低的物品的位置 P_2P2? ,並把左起第二個至 P_2P2? 間的物品 (即區間 [2,P_2][2,P2?] 間的物品) 反序……最終所有的物品都會被排好序。

技術分享圖片

上圖給出有六個物品的示例,第一次操作前,高度最低的物品在位置 44 ,於是把第一至第四的物品反序;第二次操作前,第二低的物品在位罝六,於是把第二至六的物品反序……

你的任務便是編寫一個程序,確定一個操作序列,即每次操作前第 ii 低的物品所在位置 P_iPi? ,以便機械臂工作。需要註意的是,如果有高度相同的物品,必須保證排序後它們的相對位置關系與初始時相同。

輸入輸出格式

輸入格式:

第一行包含正整數n,表示需要排序的物品數星。

第二行包含n個空格分隔的整數ai,表示每個物品的高度。

輸出格式:

輸出一行包含n個空格分隔的整數Pi。

輸入輸出樣例

輸入樣例#1:

6
3 4 5 1 6 2

輸出樣例#1:

4 6 4 5 6 6

HINT

N<=100000

Pi<=10^7

維護一個數列,支持區間翻轉,所以可以用SPLAY來維護

我們可以先將數排序,這樣他們節點數組的下標對應的就是排名

然後就是區間翻轉的操作

註意SPLAY的時候要先pushdown

技術分享圖片
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define LL long long
  6 #define lc t[x].ch[0] 
  7 #define rc t[x].ch[1]
  8 using namespace std;
  9 
 10 const int MAXN = 2e5 + 10;
 11 
 12
LL ans = 0; 13 int sum = 0; 14 int n; 15 int root; 16 int loc[MAXN]; 17 struct node { 18 int size; 19 int val; 20 int id; 21 int fa; 22 int ch[2]; 23 int lazy; 24 } t[MAXN]; 25 26 void pushdown(int x) 27 { 28 if(t[x].lazy) { 29 swap(lc, rc); 30 t[lc].lazy ^= 1; 31 t[rc].lazy ^= 1; 32 t[x].lazy ^= 1; 33 } 34 } 35 36 void pushup(int x) 37 { 38 t[x].size = t[lc].size + t[rc].size + 1; 39 } 40 inline LL read() 41 { 42 LL x = 0, w = 1; char ch = 0; 43 while(ch < 0 || ch > 9) { 44 if(ch == -) { 45 w = -1; 46 } 47 ch = getchar(); 48 } 49 while(ch >= 0 && ch <= 9) { 50 x = x * 10 + ch - 0; 51 ch = getchar(); 52 } 53 return x * w; 54 } 55 56 void rotate(int x, int &k) 57 { 58 int y = t[x].fa, z = t[y].fa; 59 int l, r; 60 if(y == k) { 61 k = x; 62 } else { 63 if(t[z].ch[0] == y) { 64 t[z].ch[0] = x; 65 } else { 66 t[z].ch[1] = x; 67 } 68 } 69 if(t[y].ch[0] == x) { 70 l = 0; 71 } else { 72 l = 1; 73 } 74 r = l ^ 1; 75 t[y].ch[l] = t[x].ch[r], t[t[x].ch[r]].fa = y; 76 t[x].fa = z, t[y].fa = x, t[x].ch[r] = y; 77 pushup(y); 78 pushup(x); 79 } 80 81 void splay(int x, int &k) 82 { 83 while(x != k) { 84 int y = t[x].fa, z = t[y].fa; 85 if(y != k) { 86 if((t[z].ch[0] == y) ^ (t[y].ch[0] == x)) { 87 rotate(x, k); 88 } else { 89 rotate(y, k); 90 } 91 } 92 rotate(x, k); 93 } 94 } 95 96 int query(int k, int x) 97 { 98 pushdown(x); 99 while(t[lc].size + 1 != k) { 100 if(t[lc].size >= k) { 101 x = lc; 102 } else { 103 k = k - t[lc].size - 1; 104 x = rc; 105 } 106 pushdown(x); 107 } 108 return x; 109 } 110 111 bool cmp(node a, node b) 112 { 113 if(a.val == b.val) { 114 return a.id < b.id; 115 } 116 return a.val < b.val; 117 } 118 119 void build(int l, int r, int &x, int last) 120 { 121 if(l > r) { 122 x = 0; 123 return; 124 } 125 int mid = (l + r) >> 1; 126 x = loc[mid]; 127 t[x].fa = last; 128 build(l, mid - 1, lc, x); 129 build(mid + 1, r, rc, x); 130 pushup(x); 131 } 132 133 void push(int x) 134 { 135 int sum = 0; 136 if(t[x].fa) { 137 push(t[x].fa); 138 pushdown(x); 139 } 140 } 141 142 void print(int x) 143 { 144 cout<<x<<" "<<t[x].size<<" "<<lc<<" "<<rc<<endl; 145 if(lc) { 146 print(lc); 147 } 148 if(rc) { 149 print(rc); 150 } 151 } 152 153 int main() 154 { 155 n = read(); 156 for(int i = 1; i <= n; i++) { 157 t[i].id = i; 158 t[i].val = read(); 159 } 160 sort(t + 1, t + n + 1, cmp); 161 for(int i = 1; i <= n; i++) { 162 loc[t[i].id] = i; 163 } 164 loc[0] = n + 2, loc[n + 1] = n + 1; 165 build(0, n + 1, root, 0); 166 for(int i = 1; i <= n; i++) { 167 push(i); 168 splay(i, root); 169 ans = t[t[root].ch[0]].size; 170 printf("%lld ", ans); 171 int loc = query(i, root); 172 splay(loc, root); 173 loc = query(ans + 2, root); 174 splay(loc, t[root].ch[1]); 175 t[t[loc].ch[0]].lazy ^= 1; 176 } 177 return 0; 178 } 179 180 181 /* 182 6 183 3 4 5 1 6 2 184 185 */
View Code

bzoj 3506[Cqoi2014]排序機械臂 - splay