標籤:des style blog http width 資料
2325: [ZJOI2011]道館之戰Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 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 Input5 3
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
Sample Output6
3
HINT
【範例說明】
第一個詢問,從房間5出發經過的冰塊數最多的路徑為:
第二個詢問,從房間4出發經過的冰塊數最多的路徑為:
【資料規模】
Source
Day2
題目描述太蛋疼了……
總結一下就是一棵樹上,每個點有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]啊啊啊啊啊啊!!!!調了一個半小時艸
/*Author:wuhuajun*/#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#define lson l, mid, rt << 1#define rson mid+1, r, rt << 1 | 1using 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;}