bzoj 1103 : [POI2007]大都市meg (树链剖分+线段树)
Description
在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了。
不过,她经常回忆起以前在乡间漫步的情景。昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双
向的土路。从每个村庄都恰好有一条路径到达村庄1(即比特堡)。并且,对于每个村庄,它到比特堡的路径恰好
只经过编号比它的编号小的村庄。另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇。在这个未开
化的地方,从来没有过高架桥和地下铁道。随着时间的推移,越来越多的土路被改造成了公路。至今,Blue Mary
还清晰地记得最后一条土路被改造为公路的情景。现在,这里已经没有土路了——所有的路都成为了公路,而昔日
的村庄已经变成了一个大都市。 Blue Mary想起了在改造期间她送信的经历。她从比特堡出发,需要去某个村庄,
并且在两次送信经历的间隔期间,有某些土路被改造成了公路.现在Blue Mary需要你的帮助:计算出每次送信她需
要走过的土路数目。(对于公路,她可以骑摩托车;而对于土路,她就只好推车了。)
Input
第一行是一个数n(1 < = n < = 2 50000).以下n-1行,每行两个整数a,b(1 < = a以下一行包含一个整数m
(1 < = m < = 2 50000),表示Blue Mary曾经在改造期间送过m次信。以下n+m-1行,每行有两种格式的若干信息
,表示按时间先后发生过的n+m-1次事件:若这行为 A a b(a若这行为 W a, 则表示Blue Mary曾经从比特堡送信到
村庄a。
Output
有m行,每行包含一个整数,表示对应的某次送信时经过的土路数目。
Sample Input
5
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3
Sample Output
2
1
0
1
1
0
1
HINT
水题
实现代码:
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1; const int M = 5e5+10; int sum[M<<2],lazy[M<<2],son[M],siz[M],head[M],top[M],fa[M],dep[M],tid[M<<2],rk[M<<2]; int u[M],v[M],cnt1,cnt,wt[M],n,m; struct node{ int to,next,w; }e[M]; void add(int u,int v){ e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1; e[++cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1; } void dfs1(int u,int faz,int deep){ dep[u] = deep; siz[u] = 1; fa[u] = faz; for(int i = head[u];i ;i=e[i].next){ int v = e[i].to; if(v != fa[u]){ wt[v] = e[i].w; dfs1(v,u,deep+1); siz[u] += siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u] = v; } } } void dfs2(int u,int t){ top[u] = t; tid[u] = cnt; //cout<<1<<endl; cnt++; if(son[u] == -1) return ; dfs2(son[u],t); for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v != son[u]&&v != fa[u]) dfs2(v,v); } } void pushup(int rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void pushdown(int rt){ if(lazy[rt]){ sum[rt<<1] = sum[rt<<1|1] = lazy[rt] = 0; lazy[rt<<1] = lazy[rt<<1|1] = 1; } } void build(int l,int r,int rt){ if(l == r){ sum[rt] = 1; return ; } mid; build(lson); build(rson); pushup(rt); } void update(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ sum[rt] = 0; lazy[rt] = 1; return ; } pushdown(rt); mid; if(L <= m) update(L,R,lson); if(R > m) update(L,R,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return sum[rt]; } pushdown(rt); mid; int ret = 0; if(L <= m) ret += query(L,R,lson); if(R > m) ret += query(L,R,rson); return ret; } void update(int x,int y){ int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy); if(fx == 1) update(tid[fx]+1,tid[x],1,n,1); else update(tid[fx],tid[x],1,n,1); x = fa[fx]; fx = top[x]; } if(x == y) return ; if(dep[x] > dep[y]) swap(x,y); update(tid[x]+1,tid[y],1,n,1); return ; } int solve(int x,int y){ int ans = 0; int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy); if(fx == 1) ans += query(tid[fx]+1,tid[x],1,n,1); else ans += query(tid[fx],tid[x],1,n,1); x = fa[fx]; fx = top[x]; } if(x == y) return ans; if(dep[x] > dep[y]) swap(x,y); ans += query(tid[x]+1,tid[y],1,n,1); return ans; } int main() { int u,v,l,r,q,x; char op[100]; scanf("%d",&n); memset(son,-1,sizeof(son)); for(int i = 2;i <= n;i ++){ scanf("%d%d",&u,&v); add(u,v); } dfs1(1,0,1); dfs2(1,0); build(1,n,1); scanf("%d",&q); q += n-1; while(q--){ scanf("%s",op); if(op[0] == 'W'){ scanf("%d",&x); printf("%d\n",solve(x,1)); } else { scanf("%d%d",&l,&r); update(l,r); } } return 0; }