2325: [ZJOI2011]道馆之战
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 813 Solved: 309
[Submit][Status]
Description
口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中的每一个冰块都只能经过一次。当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才会被打开。
三个冰地分别如下:
当走出第三个冰地之后,就可以与馆主进行道馆战了。
馆主发现这个难度太小,导致经常有挑战者能通过,为了加大难度,将道馆分成了n个房间,每个房间中是两个冰块或障碍,表示一列冰地。任意两个房间之间均有且仅有一条路径相连,即这n个房间构成一个树状结构。
每个房间分成了A和B两个区域,每一区域都是一个薄冰块或者障碍物。每次只能移动到相邻房间的同一类区域(即若你现在在这个房间的A区域,那么你只能移动到相邻房间的A区域)或这个房间的另一区域。
现在挑战者从房间u出发,馆主在房间v,那么挑战者只能朝接近馆主所在房间的方向过去。一开始挑战者可以在房间u的任意一个冰块区域内。如果挑战者踩过的冰块数达到了最大值(即没有一种方案踩过的冰块数更多了),那么当挑战者走到最后一个冰块上时,他会被瞬间传送到馆主面前与馆主进行道馆战。
自从馆主修改规则后已经经过了m天,每天要么是有一个挑战者来进行挑战,要么就是馆主将某个房间进行了修改。对于每个来的挑战者,你需要计算出他若要和馆主进行战斗需要经过的冰块数。
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
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
Sample Input
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
Sample Output
3
HINT
【样例说明】
第一个询问,从房间5出发经过的冰块数最多的路径为:
第二个询问,从房间4出发经过的冰块数最多的路径为:
【数据规模】
N≤ 30 000 |
M ≤ 80 000 |
Source
题目描述太蛋疼了……
总结一下就是一棵树上,每个点有a,b两个值,空地或者障碍,障碍就不能通过,同一个节点中a可以到b,但是a是障碍或者b是障碍就不行
询问从x到y,x从(a,b)两个点其中一个出发,最多能走多少个空地。即不要求能到达y,只求最多能走多少步
看了人家的题解,x[0..1][0..1]表示从左边的 左/右上角到 右边的 左/右上角 最多走多少步,即要求必须到达要走多少步
l[0..1]表示从左边 左/右上角出发能走多少步,r[0..1]同理
看update函数吧,不是特别麻烦,但是要注意细节
另外在树链剖分算答案的时候,由于你每条线段都是由根往下的
但x到y,从x到lca的路径是从下往上,lca到y的路径是从上往下,
也就是说求出的x到lca的路径,要反向!!!!!
妈的我只swap了l[0],r[0]和l[1]和r[1]
妈的还要swap x[0][1] 和x[1][0]啊啊啊啊啊啊!!!!调了一个半小时艹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | /* Author:wuhuajun */ #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define lson l, mid, rt << 1 #define rson mid+1, r, rt << 1 | 1 using namespace std; typedef long long ll; typedef double dd; const int maxn=100010, INF = 1000000007; int edge, n, fa[maxn], sz[maxn], son[maxn], dep[maxn], hash[maxn], top[maxn]; int h[maxn], num, a[maxn], x, y, tx, ty, Q, b[maxn]; char s[22], s1[22], s2[22]; struct Edge { int to, ne; } e[maxn * 2]; struct Seg { int x[2][2], l[2], r[2]; void clear() { x[0][0] = x[0][1] = x[1][0] = x[1][1] = 0; l[0] = l[1] = r[0] = r[1] = 0; } } seg[maxn << 2], ans, c, L, R, ret; void close() { exit (0); } void addedge( int x, int y) { e[edge].to = y; e[edge].ne = h[x]; h[x] = edge++; } void dfs( int k, int from) { sz[k] = 1; son[k] = 0; dep[k] = dep[from] + 1; for ( int p=h[k];p!=-1;p=e[p].ne) { int to = e[p].to; if (from == to) continue ; fa[to] = k; dfs(to, k); sz[k] += sz[to]; if (sz[to] > sz[son[k]]) son[k] = to; } } void build( int k, int from) { hash[k] = ++num; top[k] = from; if (son[k]) build(son[k], from); for ( int p=h[k];p!=-1;p=e[p].ne) { int to = e[p].to; if (to != fa[k] && to != son[k]) build(to, to); } } //{{{Segment部分 int cal( int x, int y) { return max(-INF, max(x, y)); } Seg operator + (Seg a,Seg b) { if (a.x[0][0] == 0 && a.x[0][1] == 0 && a.x[1][0] == 0 && a.x[1][1] == 0 && a.l[0] == 0 && a.l[1] == 0 && a.r[0] == 0 && a.r[1] == 0) return b; if (b.x[0][0] == 0 && b.x[0][1] == 0 && b.x[1][0] == 0 && b.x[1][1] == 0 && b.l[0] == 0 && b.l[1] == 0 && b.r[0] == 0 && b.r[1] == 0) return a; c.x[0][0] = cal(a.x[0][0] + b.x[0][0], a.x[0][1] + b.x[1][0]); c.x[0][1] = cal(a.x[0][0] + b.x[0][1], a.x[0][1] + b.x[1][1]); c.x[1][0] = cal(a.x[1][0] + b.x[0][0], a.x[1][1] + b.x[1][0]); c.x[1][1] = cal(a.x[1][0] + b.x[0][1], a.x[1][1] + b.x[1][1]); c.l[0] = max(a.l[0], max(a.x[0][0] + b.l[0], a.x[0][1] + b.l[1])); c.l[1] = max(a.l[1], max(a.x[1][0] + b.l[0], a.x[1][1] + b.l[1])); c.r[0] = max(b.r[0], max(b.x[0][0] + a.r[0], b.x[1][0] + a.r[1])); c.r[1] = max(b.r[1], max(b.x[0][1] + a.r[0], b.x[1][1] + a.r[1])); return c; } void change( int L, int R, int val1, int val2, int l, int r, int rt) { if (L <= l && r <= R) { seg[rt].x[0][0] = seg[rt].l[0] = seg[rt].r[0] = val1; seg[rt].x[1][1] = seg[rt].l[1] = seg[rt].r[1] = val2; if (val1 == 1 && val2 == 1) { seg[rt].l[0] = seg[rt].l[1] = seg[rt].r[0] = seg[rt].r[1] = 2; seg[rt].x[0][1] = seg[rt].x[1][0] = 2; } else { seg[rt].x[0][1] = seg[rt].x[1][0] = -INF; } seg[rt].l[0] = max(seg[rt].l[0], 0); seg[rt].l[1] = max(seg[rt].l[1], 0); seg[rt].r[0] = max(seg[rt].r[0], 0); seg[rt].r[1] = max(seg[rt].r[1], 0); return ; } int mid = (l + r) >> 1; if (L <= mid) change(L,R,val1,val2,lson); if (mid + 1 <= R) change(L,R,val1,val2,rson); seg[rt] = seg[rt << 1] + seg[rt << 1 | 1]; } Seg query( int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { return seg[rt]; } int mid = (l + r) >> 1; Seg ans; ans.clear(); if (L <= mid) ans = ans + query(L,R,lson); if (mid + 1 <= R) ans = ans + query(L,R,rson); return ans; } //}}} Seg get_ans() { tx = top[x]; ty = top[y]; L.clear(); R.clear(); while (tx != ty) { if (dep[tx] < dep[ty]) { R = query(hash[ty], hash[y], 1, n, 1) + R; y = fa[ty]; ty = top[y]; } else { L = query(hash[tx], hash[x], 1, n, 1) + L; x = fa[tx]; tx = top[x]; } } if (dep[x] < dep[y]) { R = query(hash[x], hash[y], 1, n, 1) + R; } else { L = query(hash[y], hash[x], 1, n, 1) + L; } swap(L.x[0][1], L.x[1][0]); swap(L.l[0], L.r[0]); swap(L.l[1], L.r[1]); return L + R; } void init() { scanf ( "%d %d" ,&n,&Q); memset (h,-1, sizeof (h)); for ( int i=1;i<=n-1;i++) { scanf ( "%d %d" ,&x, &y); addedge(x, y); addedge(y, x); } for ( int i=1;i<=n;i++) { scanf ( "%s" , s1); a[i] = s1[0] == '.' ? 1 : -INF; b[i] = s1[1] == '.' ? 1 : -INF; } dfs(1, 0); build(1, 1); /* for (int i=1;i<=n;i++) { printf("i:%d top:%d hash:%d\n",i, top[i], hash[i]); } */ for ( int i=1;i<=n;i++) change(hash[i], hash[i], a[i], b[i], 1, n, 1); while (Q--) { scanf ( "%s" , s); if (s[0] == 'Q' ) { scanf ( "%d %d" ,&x, &y); ret = get_ans(); printf ( "%d\n" , max(ret.l[0], ret.l[1])); } else { scanf ( "%d" ,&x); scanf ( "%s" , s1); int t1 = s1[0] == '.' ? 1 : -INF; int t2 = s1[1] == '.' ? 1 : -INF; change(hash[x], hash[x], t1, t2, 1, n, 1); } } } int main () { init(); close(); return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步