吴昊品游戏核心算法 Round 16 —— 吴昊教你玩口袋妖怪 第十弹 超能力系道馆

 

    道馆之战!!!这一次,我们将要挑战的是众人熟知的超能力系道馆,这种道馆不是火箭队的巢穴,也不是冰系道馆的那种踏冰川。何以解释?我说明如下:不同的地板上的机关有不同的颜色,每一个颜色有对应的位置,我们可以沿着给定的位置到达与之颜色相同的某个位置,此之谓对应。

  由于这一种类型的口袋妖怪场景我已经提到过了,所以,这里更换成如下的一种模式:这一种模式可谓是结合了火箭队的巢穴和冰系道馆这两者的共同优势,成为了新的一种模式的道馆。

  在这一道馆上,每一个房间只有两个区域,其中要么是冰块,要么是障碍物。这两个区域是可以互相转换的,只要都在这个房间之内就可以。而对于不同的房间来说,只能在相同的区域之间进行跳转。每一个房间只有另外一个房间与其对应,我们如果想见到道馆的BOSS,必须要尽可能多地将房间的冰块踩碎,当踩碎的冰块达到最大量的时候,我们就会通过一个转移装置见到最终的道馆BOSS了!

  这里再说的简单一点,就是:

  A)房间与房间之间是想连的,但是,又是一一映射的,也就是说,每一个房间只与唯一一个对应的房间映射。

  B)在相同的房间之内,两个区域是可以互相转换的。

  C)在不同的房间之间,只能在同一个区域之内进行转换。

  那么,我们想见到道馆的BOSS,应该怎么做呢?

 

   我们利用树链剖分算法(其数据结构为线段树)来设计一款AI,其实现的功能是可以根据道馆的地图,查看到你需要踩多少个冰块,才能见到最终的道馆BOSS

 

  Input:

 第一行包含两个正整数nm

2行到第n行,每行包含两个正整数xy,表示一条连接房间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...)

 

  1 /*
  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, 0sizeof(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  

posted on 2013-04-01 11:20  吴昊系列  阅读(619)  评论(0)    收藏  举报

导航