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
Sample Output
2
1
0
1
HINT
题目分析
树链剖板子题 路径边权+ 路径查询
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int head[250100],net[500100],to[500100],val[250100],value[250100],size[250100],fa[250100],deep[250100];
int number[250100],son[250100],top[250100];
int tot,cnt;
struct your
{
int x,y,sum;
int add;
}a[500100*2];
void add(int x,int y)
{
net[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs(int x)
{
deep[x]=deep[fa[x]]+1;
size[x]=1;
for(int i=head[x];i;i=net[i])
if(to[i]!=fa[x])
{
fa[to[i]]=x;
dfs(to[i]);
val[to[i]]=1;
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]]) son[x]=to[i];
}
}
void dfs2(int x,int temp)
{
number[x]=++cnt;
top[x]=temp;
value[cnt]=val[x];
if(son[x]) dfs2(son[x],temp);
for(int i=head[x];i;i=net[i])
if(to[i]!=son[x]&&to[i]!=fa[x])
dfs2(to[i],to[i]);
}
void pushdown(int num)
{
a[num<<1].add=a[num<<1|1].add=1;
a[num<<1].sum=a[num<<1|1].sum=0;
a[num].add=0;
}
void build(int dx,int dy,int num)
{
a[num].x=dx,a[num].y=dy;
if(dx==dy)
{
a[num].sum=value[dx];
return ;
}
int mid=(dx+dy)>>1;
build(dx,mid,num<<1),build(mid+1,dy,num<<1|1);
a[num].sum=a[num<<1].sum+a[num<<1|1].sum;
return ;
}
void update(int dx,int dy,int num)
{
if(a[num].x==dx&&a[num].y==dy)
{
a[num].add=1,a[num].sum=0;
return ;
}
if(a[num].add) pushdown(num);
int mid=(a[num].x+a[num].y)>>1;
if(dx>mid) update(dx,dy,num<<1|1);
else if(dy<=mid) update(dx,dy,num<<1);
else update(dx,mid,num<<1),update(mid+1,dy,num<<1|1);
a[num].sum=a[num<<1].sum+a[num<<1|1].sum;
}
int ask(int dx,int dy,int num)
{
if(a[num].x==dx&&a[num].y==dy)
return a[num].sum;
if(a[num].add) pushdown(num);
int mid=(a[num].x+a[num].y)>>1;
if(dx>mid) return ask(dx,dy,num<<1|1);
if(dy<=mid) return ask(dx,dy,num<<1);
return ask(dx,mid,num<<1)+ask(mid+1,dy,num<<1|1);
}
void change(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
update(number[top[x]],number[x],1);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
if(x==y) return ;
update(number[x]+1,number[y],1);
}
int find(int x,int y)
{
int sum=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
sum+=ask(number[top[x]],number[x],1);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
if(x==y) return sum;
return sum+ask(number[x]+1,number[y],1);
}
char s[10];
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs(1),dfs2(1,1);
build(1,n,1);
scanf("%d",&m);
for(int i=1;i<=n+m-1;i++)
{
int x,y;
scanf("%s",&s[0]);
if(s[0]=='A')
{
scanf("%d%d",&x,&y);
change(x,y);
}
else
{
scanf("%d",&x);
printf("%d\n",find(1,x));
}
}
}