bzoj2325 [ZJOI2011]道馆之战
2325: [ZJOI2011]道馆之战
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1340 Solved: 501
[Submit][Status][Discuss]
Description
Input
Output
包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。
Sample Input
1 2
2 3
2 4
1 5
.#
..
#.
.#
..
Q 5 3
C 1 ##
Q 4 5
Sample Output
3
c.dis[0][0] = max(-inf,max(a.dis[0][0] + b.dis[0][0],a.dis[0][1] + b.dis[1][0]));
c.dis[1][1] = max(-inf,max(a.dis[1][1] + b.dis[1][1],a.dis[1][0] + b.dis[0][1]));
c.dis[0][1] = max(-inf,max(a.dis[0][0] + b.dis[0][1],a.dis[0][1] + b.dis[1][1]));
c.dis[1][0] = max(-inf,max(a.dis[1][1] + b.dis[1][0],a.dis[1][0] + b.dis[0][0]));
c.maxx[0][0] = max(a.maxx[0][0],max(a.dis[0][0] + b.maxx[0][0],a.dis[0][1] + b.maxx[0][1]));
c.maxx[0][1] = max(a.maxx[0][1],max(a.dis[1][0] + b.maxx[0][0],a.dis[1][1] + b.maxx[0][1]));
c.maxx[1][0] = max(b.maxx[1][0],max(b.dis[0][0] + a.maxx[1][0],b.dis[1][0] + a.maxx[1][1]));
c.maxx[1][1] = max(b.maxx[1][1],max(b.dis[0][1] + a.maxx[1][0],b.dis[1][1] + a.maxx[1][1]));
在树上怎么办呢?每次询问的是两个点之间的路径,很显然,要用线段树+树链剖分. 如果询问的两个点分别是x,y,令lans表示x向上跳得到的答案,rans表示y向上跳得到的答案,最后要将lans取反再与rans合并,因为当两个点最后跳到一起时,它们的左端点对应左端点,右端点对应右端点,而我们要求左端点对应右端点,右端点对应左端点,所以要取反:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 30010,inf = (1 << 30); int n,m,head[maxn],to[maxn * 2],nextt[maxn * 2],tot = 1,sizee[maxn],son[maxn],top[maxn]; int pos[maxn],id[maxn],dfs_clock,fa[maxn],a[maxn][2],deep[maxn]; struct node { int dis[2][2],maxx[2][2]; void clear() { memset(dis,0,sizeof(dis)); memset(maxx,0,sizeof(maxx)); } bool emptyy() { if (!dis[0][0] && !dis[0][1] && !dis[1][0] && !dis[1][1] && !maxx[0][0] && !maxx[0][1] && !maxx[1][0] && !maxx[1][1]) return true; return false; } }e[maxn << 2]; void add(int x,int y) { to[tot] = y; nextt[tot] = head[x]; head[x] = tot++; } void dfs1(int u,int faa) { fa[u] = faa; sizee[u] = 1; deep[u] = deep[faa] + 1; for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (v == faa) continue; dfs1(v,u); sizee[u] += sizee[v]; if (sizee[v] > sizee[son[u]]) son[u] = v; } } void dfs2(int u,int topp) { top[u] = topp; pos[u] = ++dfs_clock; id[dfs_clock] = u; if (son[u]) dfs2(son[u],topp); for (int i = head[u]; i; i = nextt[i]) { int v = to[i]; if (v == fa[u] || v == son[u]) continue; dfs2(v,v); } } node pushup(node a,node b) { node c; if (a.emptyy()) c = b; else if (b.emptyy()) c = a; else { c.dis[0][0] = max(-inf,max(a.dis[0][0] + b.dis[0][0],a.dis[0][1] + b.dis[1][0])); c.dis[1][1] = max(-inf,max(a.dis[1][1] + b.dis[1][1],a.dis[1][0] + b.dis[0][1])); c.dis[0][1] = max(-inf,max(a.dis[0][0] + b.dis[0][1],a.dis[0][1] + b.dis[1][1])); c.dis[1][0] = max(-inf,max(a.dis[1][1] + b.dis[1][0],a.dis[1][0] + b.dis[0][0])); c.maxx[0][0] = max(a.maxx[0][0],max(a.dis[0][0] + b.maxx[0][0],a.dis[0][1] + b.maxx[0][1])); c.maxx[0][1] = max(a.maxx[0][1],max(a.dis[1][0] + b.maxx[0][0],a.dis[1][1] + b.maxx[0][1])); c.maxx[1][0] = max(b.maxx[1][0],max(b.dis[0][0] + a.maxx[1][0],b.dis[1][0] + a.maxx[1][1])); c.maxx[1][1] = max(b.maxx[1][1],max(b.dis[0][1] + a.maxx[1][0],b.dis[1][1] + a.maxx[1][1])); } return c; } void build(int o,int l,int r) { if (l == r) { int p = a[id[l]][0],q = a[id[l]][1]; if (p == 1 && q == 1) { e[o].dis[0][0] = e[o].dis[1][1] = 1; e[o].dis[0][1] = e[o].dis[1][0] = 2; e[o].maxx[0][0] = e[o].maxx[0][1] = e[o].maxx[1][0] = e[o].maxx[1][1] = 2; } else if (p == 1) { e[o].dis[0][0] = 1; e[o].dis[0][1] = e[o].dis[1][0] = e[o].dis[1][1] = -inf; e[o].maxx[0][0] = e[o].maxx[1][0] = 1; e[o].maxx[0][1] = e[o].maxx[1][1] = -inf; } else if (q == 1) { e[o].dis[0][0] = e[o].dis[0][1] = e[o].dis[1][0] = -inf; e[o].dis[1][1] = 1; e[o].maxx[0][0] = e[o].maxx[1][0] = -inf;; e[o].maxx[0][1] = e[o].maxx[1][1] = 1; } else { for (int i = 0; i <= 1; i++) for (int j = 0; j <= 1; j++) e[o].dis[i][j] = e[o].maxx[i][j] = -inf; } return; } int mid = (l + r) >> 1; build(o * 2,l,mid); build(o * 2 + 1,mid + 1,r); e[o] = pushup(e[o * 2],e[o * 2 + 1]); } void update(int o,int l,int r,int v,int p,int q) { if (l == r) { if (p == 1 && q == 1) { e[o].dis[0][0] = e[o].dis[1][1] = 1; e[o].dis[0][1] = e[o].dis[1][0] = 2; e[o].maxx[0][0] = e[o].maxx[0][1] = e[o].maxx[1][0] = e[o].maxx[1][1] = 2; } else if (p == 1) { e[o].dis[0][0] = 1; e[o].dis[0][1] = e[o].dis[1][0] = e[o].dis[1][1] = -inf; e[o].maxx[0][0] = e[o].maxx[1][0] = 1; e[o].maxx[0][1] = e[o].maxx[1][1] = -inf; } else if (q == 1) { e[o].dis[0][0] = e[o].dis[0][1] = e[o].dis[1][0] = -inf; e[o].dis[1][1] = 1; e[o].maxx[0][0] = e[o].maxx[1][0] = -inf;; e[o].maxx[0][1] = e[o].maxx[1][1] = 1; } else { for (int i = 0; i <= 1; i++) for (int j = 0; j <= 1; j++) e[o].dis[i][j] = e[o].maxx[i][j] = -inf; } return; } int mid = (l + r) >> 1; if (v <= mid) update(o * 2,l,mid,v,p,q); else update(o * 2 + 1,mid + 1,r,v,p,q); e[o] = pushup(e[o * 2],e[o * 2 + 1]); } node fan(node a) { swap(a.maxx[0][0],a.maxx[1][0]); swap(a.maxx[0][1],a.maxx[1][1]); swap(a.dis[0][1],a.dis[1][0]); return a; } node query(int o,int l,int r,int x,int y) { if (l == x && r == y) return e[o]; int mid = (l + r) >> 1; if (y <= mid) return query(o * 2,l,mid,x,y); else if (x > mid) return query(o * 2 + 1,mid + 1,r,x,y); else return pushup(query(o * 2,l,mid,x,mid),query(o * 2 + 1,mid + 1,r,mid + 1,y)); } int Query(int x,int y) { node lans,rans; lans.clear(); rans.clear(); while (top[x] != top[y]) { if (deep[top[x]] < deep[top[y]]) { rans = pushup(query(1,1,n,pos[top[y]],pos[y]),rans); y = fa[top[y]]; } else { lans = pushup(query(1,1,n,pos[top[x]],pos[x]),lans); x = fa[top[x]]; } } if (deep[x] > deep[y]) lans = pushup(query(1,1,n,pos[y],pos[x]),lans); else rans = pushup(query(1,1,n,pos[x],pos[y]),rans); lans = pushup(fan(lans),rans); int temp = max(lans.maxx[0][0],lans.maxx[0][1]); if (temp < 0) temp = 0; return temp; } int main() { scanf("%d%d",&n,&m); for (int i = 1; i < n; i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(1,0); dfs2(1,1); for (int i = 1; i <= n; i++) { char ch[3]; scanf("%s",ch); if (ch[0] == '.') a[i][0] = 1; else a[i][0] = 0; if (ch[1] == '.') a[i][1] = 1; else a[i][1] = 0; } build(1,1,n); while (m--) { char ch[2],s[3]; scanf("%s",ch); int u,v,p,q; if (ch[0] == 'C') { scanf("%d",&u); scanf("%s",s); if (s[0] == '.') p = 1; else p = 0; if (s[1] == '.') q = 1; else q = 0; update(1,1,n,pos[u],p,q); } else { scanf("%d%d",&u,&v); printf("%d\n",Query(u,v)); } } return 0; }