吴昊品游戏核心算法 Round 16 —— 吴昊教你玩口袋妖怪 第十弹 超能力系道馆
道馆之战!!!这一次,我们将要挑战的是众人熟知的超能力系道馆,这种道馆不是火箭队的巢穴,也不是冰系道馆的那种踏冰川。何以解释?我说明如下:不同的地板上的机关有不同的颜色,每一个颜色有对应的位置,我们可以沿着给定的位置到达与之颜色相同的某个位置,此之谓对应。
由于这一种类型的口袋妖怪场景我已经提到过了,所以,这里更换成如下的一种模式:这一种模式可谓是结合了火箭队的巢穴和冰系道馆这两者的共同优势,成为了新的一种模式的道馆。
在这一道馆上,每一个房间只有两个区域,其中要么是冰块,要么是障碍物。这两个区域是可以互相转换的,只要都在这个房间之内就可以。而对于不同的房间来说,只能在相同的区域之间进行跳转。每一个房间只有另外一个房间与其对应,我们如果想见到道馆的BOSS,必须要尽可能多地将房间的冰块踩碎,当踩碎的冰块达到最大量的时候,我们就会通过一个转移装置见到最终的道馆BOSS了!
这里再说的简单一点,就是:
(A)房间与房间之间是想连的,但是,又是一一映射的,也就是说,每一个房间只与唯一一个对应的房间映射。
(B)在相同的房间之内,两个区域是可以互相转换的。
(C)在不同的房间之间,只能在同一个区域之内进行转换。
那么,我们想见到道馆的BOSS,应该怎么做呢?
我们利用树链剖分算法(其数据结构为线段树)来设计一款AI,其实现的功能是可以根据道馆的地图,查看到你需要踩多少个冰块,才能见到最终的道馆BOSS。
Input:
第一行包含两个正整数n和m。
第2行到第n行,每行包含两个正整数x和y,表示一条连接房间x和房间y的边。房间编号为1…n。
接下来n行,每行包含两个字符。第n + k行表示房间k的两个区域,第一个字符为A区域,第二个字符为B区域。其中“.”(ASCII码为46)表示是薄冰块,“#”(ASCII码为35)表示是障碍物。
最后的m行,每行一个操作:
l C u s:将房间u里的两个区域修改为s。
l Q u v:询问挑战者在房间u,馆主在房间v时,挑战者能与馆主进行挑战需要踩的冰块数。如果房间u的两个区域都是障碍物,那么输出0。
Output:
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
Solve:
很明显是树链剖分,但是重点就在于要维护什么。对于一段路径,我们关心的只是从路径一端的某个区域向另一端的某个区域走可以走多远,所以对于每个点要记录3个值:f[0..1][0..1],l[0..1],r[0..1],分别表示两端某两个区域之间的最长路,从左端点某个区域出发的最长路和右端点的。。这样,就可以在线段树很方便地进行维护。
(此为转载,关于线段树的树链剖分,我还各种搞不懂,作者为LTL...)
2
3 Author: LTL
4
5 Data: 2011-6-8
6
7 */
8
9
10
11 #include <iostream>
12
13 #include <memory.h>
14
15 #include <cstdio>
16
17 #include <cstdlib>
18
19 #include <algorithm>
20
21 #include <cmath>
22
23
24
25 #define InputFileName "Data.in"
26
27 #define OutputFileName "Data.out"
28
29 #define Max(a, b) (a > b ? a : b)
30
31
32
33 using namespace std;
34
35
36
37 const int MaxN = 31000, MaxE = MaxN*2, oo = 1000000000;
38
39
40
41 int n, m, Next[MaxE], v[MaxE], Head[MaxN], ENum, Total, d[MaxE][20], Depth[MaxN], Size[MaxN], Heavy[MaxN], Father[MaxN], Pos[MaxN];
42
43 bool View[MaxN];
44
45 int Seq[MaxN], STNum[MaxN], STPos[MaxN], STSize[MaxN], STTail[MaxN], Root[MaxN], STTotal, Left[MaxN*4], Right[MaxN*4], f[MaxN*4][2][2], L[MaxN*4][2], R[MaxN*4][2];
46
47 char a[MaxN][3];
48
49
50
51 inline void AddEdge(const int x, const int y)
52
53 {
54
55 Next[++ENum] = Head[x];
56
57 v[Head[x] = ENum] = y;
58
59 }
60
61
62
63 void Init()
64
65 {
66
67 scanf("%d%d", &n, &m);
68
69 for (int i = 1, x, y; i < n; ++i)
70
71 {
72
73 scanf("%d%d", &x, &y);
74
75 AddEdge(x, y);
76
77 AddEdge(y, x);
78
79 }
80
81 for (int i = 1; i <= n; ++i)
82
83 scanf("%s", a[i]);
84
85 }
86
87
88
89 void DFS(const int t)
90
91 {
92
93 View[t] = Size[t] = 1;
94
95 d[Pos[t] = ++Total][0] = t;
96
97 for (int i = Head[t]; i; i = Next[i])
98
99 if (! View[v[i]])
100
101 {
102
103 Depth[v[i]] = Depth[t]+1;
104
105 Father[v[i]] = t;
106
107 DFS(v[i]);
108
109 Size[t] += Size[v[i]];
110
111 d[++Total][0] = t;
112
113 if (! Heavy[t] || Size[v[i]] > Size[Heavy[t]])
114
115 Heavy[t] = v[i];
116
117 }
118
119 }
120
121
122
123 inline int RMQMin(const int x, const int y)
124
125 {
126
127 return Depth[x] < Depth[y] ? x : y;
128
129 }
130
131
132
133 inline int LCA(int x, int y)
134
135 {
136
137 if ((x = Pos[x]) > (y = Pos[y]))
138
139 swap(x, y);
140
141 const int k = (int)log2(y-x+1);
142
143 return RMQMin(d[x][k], d[y-(1 << k)+1][k]);
144
145 }
146
147
148
149 inline void Combine(int c[2][2], int a[2][2], int b[2][2])
150
151 {
152
153 int Res[2][2];
154
155 Res[0][0] = Max(a[0][0]+b[0][0], a[0][1]+b[1][0]);
156
157 Res[0][1] = Max(a[0][0]+b[0][1], a[0][1]+b[1][1]);
158
159 Res[1][0] = Max(a[1][0]+b[0][0], a[1][1]+b[1][0]);
160
161 Res[1][1] = Max(a[1][0]+b[0][1], a[1][1]+b[1][1]);
162
163 c[0][0] = Max(Res[0][0], -oo);
164
165 c[0][1] = Max(Res[0][1], -oo);
166
167 c[1][0] = Max(Res[1][0], -oo);
168
169 c[1][1] = Max(Res[1][1], -oo);
170
171 }
172
173
174
175 inline void CalcL(int c[2], int s[2][2], int a[2], int b[2])
176
177 {
178
179 int r[2];
180
181 r[0] = Max(s[0][0]+b[0], s[0][1]+b[1]);
182
183 r[1] = Max(s[1][1]+b[1], s[1][0]+b[0]);
184
185 c[0] = Max(r[0], a[0]);
186
187 c[1] = Max(r[1], a[1]);
188
189 }
190
191
192
193 inline void CalcR(int c[2], int s[2][2], int a[2], int b[2])
194
195 {
196
197 int r[2];
198
199 r[0] = Max(a[0]+s[0][0], a[1]+s[1][0]);
200
201 r[1] = Max(a[1]+s[1][1], a[0]+s[0][1]);
202
203 c[0] = Max(r[0], b[0]);
204
205 c[1] = Max(r[1], b[1]);
206
207 }
208
209
210
211 void Build(int &t, const int l, const int r)
212
213 {
214
215 t = ++Total;
216
217 if (l == r)
218
219 {
220
221 f[t][0][0] = a[Seq[l]][0] == '.' ? 1 : -oo;
222
223 f[t][0][1] = f[t][1][0] = a[Seq[l]][0] == '.' && a[Seq[l]][1] == '.' ? 2 : -oo;
224
225 f[t][1][1] = a[Seq[l]][1] == '.' ? 1 : -oo;
226
227 L[t][0] = Max(f[t][0][0], f[t][0][1]);
228
229 L[t][1] = Max(f[t][1][0], f[t][1][1]);
230
231 L[t][0] = Max(L[t][0], 0);
232
233 L[t][1] = Max(L[t][1], 0);
234
235 memcpy(R[t], L[t], sizeof(L[t]));
236
237 return;
238
239 }
240
241 const int mid = l+r >> 1;
242
243 Build(Left[t], l, mid);
244
245 Build(Right[t], mid+1, r);
246
247 Combine(f[t], f[Left[t]], f[Right[t]]);
248
249 CalcL(L[t], f[Left[t]], L[Left[t]], L[Right[t]]);
250
251 CalcR(R[t], f[Right[t]], R[Left[t]], R[Right[t]]);
252
253 }
254
255
256
257 void Modify(const int t, const int l, const int r, const int p, const int k)
258
259 {
260
261 if (l == r)
262
263 {
264
265 f[t][0][0] = a[k][0] == '.' ? 1 : -oo;
266
267 f[t][0][1] = f[t][1][0] = a[k][0] == '.' && a[k][1] == '.' ? 2 : -oo;
268
269 f[t][1][1] = a[k][1] == '.' ? 1 : -oo;
270
271 L[t][0] = Max(f[t][0][0], f[t][0][1]);
272
273 L[t][1] = Max(f[t][1][0], f[t][1][1]);
274
275 L[t][0] = Max(L[t][0], 0);
276
277 L[t][1] = Max(L[t][1], 0);
278
279 memcpy(R[t], L[t], sizeof(L[t]));
280
281 return;
282
283 }
284
285 const int mid = l+r >> 1;
286
287 if (p <= mid)
288
289 Modify(Left[t], l, mid, p, k);
290
291 else
292
293 Modify(Right[t], mid+1, r, p, k);
294
295 Combine(f[t], f[Left[t]], f[Right[t]]);
296
297 CalcL(L[t], f[Left[t]], L[Left[t]], L[Right[t]]);
298
299 CalcR(R[t], f[Right[t]], R[Left[t]], R[Right[t]]);
300
301 }
302
303
304
305 void Query(const int t, const int l, const int r, const int x, const int y, int Res[2][2], int rL[2], int rR[2])
306
307 {
308
309 if (x <= l && y >= r)
310
311 {
312
313 memcpy(Res, f[t], sizeof(f[t]));
314
315 memcpy(rL, L[t], sizeof(L[t]));
316
317 memcpy(rR, R[t], sizeof(R[t]));
318
319 return;
320
321 }
322
323 const int mid = l+r >> 1;
324
325 int tmp[2][2], tmpL[2], tmpR[2];
326
327 if (x <= mid)
328
329 Query(Left[t], l, mid, x, y, Res, rL, rR);
330
331 if (y > mid)
332
333 Query(Right[t], mid+1, r, x, y, tmp, tmpL, tmpR);
334
335 if (x <= mid && y > mid)
336
337 {
338
339 CalcL(rL, Res, rL, tmpL);
340
341 CalcR(rR, tmp, rR, tmpR);
342
343 Combine(Res, Res, tmp);
344
345 }
346
347 else if (y > mid)
348
349 {
350
351 memcpy(Res, tmp, sizeof(tmp));
352
353 memcpy(rL, tmpL, sizeof(tmpL));
354
355 memcpy(rR, tmpR, sizeof(tmpR));
356
357 }
358
359 }
360
361
362
363 void Prework()
364
365 {
366
367 DFS(1);
368
369 for (int i, j = 1, k = (int)log2(Total); j <= k; ++j)
370
371 for (i = 1; i+(1 << j)-1 <= Total; ++i)
372
373 d[i][j] = RMQMin(d[i][j-1], d[i+(1 << j-1)][j-1]);
374
375 Total = 0;
376
377 memset(View, 0, sizeof(View));
378
379 for (int i = 1, j; i <= n; ++i)
380
381 if (! View[i])
382
383 {
384
385 for (j = i; Heavy[j]; j = Heavy[j]);
386
387 ++STTotal;
388
389 for (View[j] = 1; Heavy[Father[j]] == j; View[j = Father[j]] = 1)
390
391 Seq[STPos[j] = ++STSize[STNum[j] = STTotal]] = j;
392
393 Seq[STPos[STTail[STTotal] = j] = ++STSize[STNum[j] = STTotal]] = j;
394
395 Build(Root[STTotal], 1, STSize[STTotal]);
396
397 }
398
399 }
400
401
402
403 void Ask1(int x, const int y, int Res[2][2], int rL[2], int rR[2])
404
405 {
406
407 if (STNum[x] == STNum[y])
408
409 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STPos[y], Res, rL, rR);
410
411 else
412
413 {
414
415 int tmpL[2], tmpR[2], tmp[2][2];
416
417 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STSize[STNum[x]], Res, rL, rR);
418
419 x = Father[STTail[STNum[x]]];
420
421 for (; STNum[x] != STNum[y]; x = Father[STTail[STNum[x]]])
422
423 {
424
425 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STSize[STNum[x]], tmp, tmpL, tmpR);
426
427 CalcL(rL, Res, rL, tmpL);
428
429 CalcR(rR, tmp, rR, tmpR);
430
431 Combine(Res, Res, tmp);
432
433 }
434
435 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STPos[y], tmp, tmpL, tmpR);
436
437 CalcL(rL, Res, rL, tmpL);
438
439 CalcR(rR, tmp, rR, tmpR);
440
441 Combine(Res, Res, tmp);
442
443 }
444
445 }
446
447
448
449 void Ask2(int x, const int y, int Res[2][2], int rL[2], int rR[2])
450
451 {
452
453 if (STNum[x] == STNum[y])
454
455 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STPos[y]-1, Res, rL, rR);
456
457 else
458
459 {
460
461 int tmpL[2], tmpR[2], tmp[2][2];
462
463 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STSize[STNum[x]], Res, rL, rR);
464
465 x = Father[STTail[STNum[x]]];
466
467 for (; STNum[x] != STNum[y]; x = Father[STTail[STNum[x]]])
468
469 {
470
471 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STSize[STNum[x]], tmp, tmpL, tmpR);
472
473 CalcL(rL, Res, rL, tmpL);
474
475 CalcR(rR, tmp, rR, tmpR);
476
477 Combine(Res, Res, tmp);
478
479 }
480
481 if (STPos[y] > STPos[x])
482
483 {
484
485 Query(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], STPos[y]-1, tmp, tmpL, tmpR);
486
487 CalcL(rL, Res, rL, tmpL);
488
489 CalcR(rR, tmp, rR, tmpR);
490
491 Combine(Res, Res, tmp);
492
493 }
494
495 }
496
497 }
498
499
500
501 int main()
502
503 {
504
505 #ifndef ONLINE_JUDGE
506
507 freopen(InputFileName, "r", stdin);
508
509 freopen(OutputFileName, "w", stdout);
510
511 #endif
512
513 Init();
514
515 Prework();
516
517 char cmd[2];
518
519 for (int x, y, lca, tmp[2][2], Res[2][2], Ans, rL[2], rR[2], tmpL[2], tmpR[2]; m; --m)
520
521 {
522
523 scanf("%s%d", cmd, &x);
524
525 if (cmd[0] == 'C')
526
527 {
528
529 scanf("%s", a[x]);
530
531 Modify(Root[STNum[x]], 1, STSize[STNum[x]], STPos[x], x);
532
533 }
534
535 else
536
537 {
538
539 scanf("%d", &y);
540
541 lca = LCA(x, y);
542
543 Ask1(x, lca, Res, rL, rR);
544
545 if (y != lca)
546
547 {
548
549 Ask2(y, lca, tmp, tmpR, tmpL);
550
551 swap(tmp[0][1], tmp[1][0]);
552
553 CalcL(rL, Res, rL, tmpL);
554
555 CalcR(rR, tmp, rR, tmpR);
556
557 Combine(Res, Res, tmp);
558
559 }
560
561 Ans = Max(rL[0], rL[1]);
562
563 printf("%d\n", Ans);
564
565 }
566
567 }
568
569 return 0;
570
571 }
572
573
浙公网安备 33010602011771号