【Codeforces-420D】Cup Trick(无旋treap-平衡树)
题目传送门:https://codeforces.com/problemset/problem/420/D
题意:给出m次操作,每次操作输入两个值x,y,将y位置值为x的数移到最前面,让你求一个长度为n的初始序列满足所要进行操作的条件。
思路:由于初始序列未知,我们可以将序列都设为0,然后按操作进行,如果进行操作时,y位置为0,说明这个位置没有动过,可以为之前操作中没有操作过的值(比如说,如果你上一步操作把3位置的1移到了最前面,那么这一步操作你不能将这个位置的1移到最前面,因为这个位置的值不是1,如果这个位置在最前面的话,那么位置的值就不是0而是1了),那么我们可以将这个位置的值设为x,并移到最前面的位置,如果在操作的过程中遇到了重复操作的值,或者位置上的值与所操作的值不吻合的话说明这个初始序列是不存在的,那么就直接输出-1。
具体实现:我们可以用平衡树来维护这个序列,利用平衡树是有序的,来维护每次操作将值移到最前面的过程,我们可以将平衡树的val作为序列排序的对比值,大的val在最后面,小的val在最前面,每次操作可以是之前的val-1就可以了,emm,具体实现还是看代码吧。
1 #pragma GCC optimize("O3") 2 #pragma G++ optimize("O3") 3 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<iostream> 8 #include<set> 9 #include<queue> 10 #include<map> 11 //#define int long long 12 using namespace std; 13 const int MAXN = 2000010; 14 const int MOD = 2147483647; 15 16 int inf = 2000005; 17 18 //inline int read() { 19 // char a = getchar(); 20 // int x = 0, f = 1;//f判断正负数 21 // while (a < '0' || a > '9') { 22 // if (a == '-') f = -1; 23 // a = getchar(); 24 // } 25 // while (a >= '0' && a <= '9') { 26 // x = x * 10 + (a - '0'); 27 // a = getchar(); 28 // } 29 // return x * f; 30 //} 31 //inline void write(int x) { 32 // if (x < 0) { 33 // putchar('-'); 34 // x = -x; 35 // } 36 // if (x > 9) write(x / 10); 37 // putchar(x % 10 + '0'); 38 //} 39 40 queue<int>q; 41 42 struct Node 43 { 44 int left; //左子树 45 int right; //右子树 46 int size; //大小 47 int val; //值 48 int key; //平衡种子 49 int real; 50 51 }tree[MAXN]; 52 53 int root, tot; 54 55 inline int add(int val, int real) { 56 tot++; 57 tree[tot].size = 1; 58 tree[tot].val = val; 59 tree[tot].key = rand() % MOD; 60 tree[tot].left = 0; 61 tree[tot].right = 0; 62 tree[tot].real = real; 63 64 return tot; 65 } 66 67 inline void update_root(int now) { 68 int left, right; 69 70 left = tree[now].left; 71 right = tree[now].right; 72 73 tree[now].size = tree[left].size + tree[right].size + 1; 74 } 75 76 //拆分(now原treap,a左子树,b右子树,val值) 77 inline void split_new(int now, int& a, int& b, int val) { 78 if (now == 0) { 79 a = 0; 80 b = 0; 81 return; 82 } 83 84 if (tree[now].val <= val) {//now左子树中的所有值都小于now, 85 a = now; 86 split_new(tree[now].right, tree[a].right, b, val); 87 } 88 else { 89 b = now; 90 split_new(tree[now].left, a, tree[b].left, val); 91 } 92 93 update_root(now); 94 } 95 96 inline void merge_new(int& now, int a, int b) { 97 if (a == 0 || b == 0) { 98 now = a + b; 99 return; 100 } 101 102 //按照key值合并(堆性质) 103 if (tree[a].key < tree[b].key) { 104 /** 105 * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代, 106 * a的左子树不变,直接赋给now,递归合并a的右子树和b 107 */ 108 now = a; 109 merge_new(tree[now].right, tree[a].right, b); 110 } 111 else { 112 now = b; 113 merge_new(tree[now].left, a, tree[b].left); 114 } 115 116 update_root(now); 117 } 118 119 int pos, value; 120 inline void find_new(int now, int rank) {//找第k大 121 while (tree[tree[now].left].size + 1 != rank) { 122 if (tree[tree[now].left].size >= rank) { 123 now = tree[now].left; 124 } 125 else { 126 rank -= tree[tree[now].left].size + 1; 127 now = tree[now].right; 128 } 129 } 130 pos = tree[now].val; 131 value = tree[now].real; 132 //cout << tree[now].val << " " << tree[now].real << "\n"; 133 } 134 135 inline void insert_new(int val, int real) { 136 int x, y, z; 137 138 x = 0; 139 y = 0; 140 z = add(val, real); 141 split_new(root, x, y, val); 142 merge_new(x, x, z); 143 merge_new(root, x, y); 144 } 145 146 inline void del_new(int val) { 147 int x, y, z; 148 149 x = y = z = 0; 150 split_new(root, x, y, val); 151 split_new(x, x, z, val - 1); 152 merge_new(z, tree[z].left, tree[z].right); 153 merge_new(x, x, z); 154 merge_new(root, x, y); 155 } 156 157 inline void get_rank(int val) { 158 int x, y; 159 160 x = y = 0; 161 split_new(root, x, y, val - 1); 162 cout << tree[x].size + 1 << "\n"; 163 merge_new(root, x, y); 164 } 165 166 inline void get_val(int rank) { 167 find_new(root, rank); 168 } 169 170 inline void get_pre(int val) { 171 int x, y; 172 173 x = y = 0; 174 split_new(root, x, y, val - 1); 175 find_new(x, tree[x].size); 176 merge_new(root, x, y); 177 } 178 179 inline void get_next(int val) { 180 int x, y; 181 182 x = y = 0; 183 split_new(root, x, y, val); 184 find_new(y, 1); 185 merge_new(root, x, y); 186 } 187 188 int mp[2000010]; 189 int vis[1000005]; 190 int sp[2000010]; 191 192 int main() { 193 194 ios::sync_with_stdio(false); 195 cin.tie(0); 196 cout.tie(0); 197 int n, m; 198 //cin >> n >> m; 199 int rem = 0; 200 cin >> n >> m; 201 202 203 //memset(tree, 0, sizeof(tree)); 204 205 add(MOD, 0); 206 root = 1; 207 tree[root].size = 0; 208 209 /*insert_new(2, 99); 210 insert_new(1, 87); 211 insert_new(3, 35); 212 get_val(2); 213 del_new(2); 214 get_val(2);*/ 215 216 /*3 3 217 1 3 218 2 3 219 3 3*/ 220 221 int flag = 1; 222 for (int i = 1; i <= n; i++) { 223 //s.insert(i); 224 insert_new(inf - i, 0); //利用val值来排序,val只需要不断递减,就可以保证每次操作都可以移动到最前面 225 //get_val(1); 226 } 227 int cnt = inf - n; 228 set<int>::iterator it; 229 /*if (n == 1000000 && m == 1000000) { 230 cout << -1 << "\n"; 231 return 0; 232 }*/ 233 int x, y; 234 for (; m; --m) { 235 cin >> x >> y; 236 /*x = read(); 237 y = read();*/ 238 //if (i >= 500000) continue; 239 //if (!flag) continue; 240 get_val(y); 241 if (value == x || value == 0) { 242 if (value == 0 && vis[x]) { 243 flag = 0; 244 //write(-1); 245 cout << -1; 246 return 0; 247 } 248 del_new(pos); 249 insert_new(--cnt, x); 250 251 //if (!vis[x]) { 252 // /*it = s.find(x); 253 // s.erase(it);*/ 254 // sp[x] = 1; 255 //} 256 if (mp[pos] == 0 && !vis[x]) { 257 mp[pos] = x; 258 vis[x] = 1; 259 sp[x] = 1; 260 } 261 262 } 263 else { 264 flag = 0; 265 //write(-1); 266 cout << -1; 267 return 0; 268 //cout << -1 << "\n"; 269 } 270 } 271 /*if (n == 1000000 && m == 1000000) { 272 cout << -1 << "\n"; 273 return 0; 274 }*/ 275 if (flag) { 276 /*it = s.begin(); 277 while (it != s.end()) { 278 q.push(*it); 279 it++; 280 }*/ 281 for (int i = 1; i <= n; i++) { 282 if (!sp[i]) { 283 q.push(i); 284 } 285 } 286 /*for (int i = 1; i <= n; i++) { 287 get_val(i); 288 if (value == 0) { 289 int p = q.front(); 290 q.pop(); 291 cout << p << " "; 292 } 293 else cout << value << " "; 294 }*/ 295 //int itt = inf; 296 for (int i = inf - n; i <= inf - 1; i++) { 297 // pp; 298 //mp[i] != 0 ? write(mp[i]), putchar(' ') : pp = q.front(), q.pop(), printf("%d", pp), putchar(' '); 299 if (mp[i] != 0) { 300 //cout << mp[i] << " "; 301 cout << mp[i] << " "; 302 //putchar(' '); 303 } 304 else { 305 int pp = q.front(); 306 q.pop(); 307 cout << pp << " "; 308 /*write(pp); 309 putchar(' ');*/ 310 } 311 } 312 } 313 else cout << -1; 314 315 return 0; 316 }
永远热爱,永远向着光。

浙公网安备 33010602011771号