题解:
维护x到1的土路条数;
修改一条边相当于修改一个区间;
用树状数组差分实现
对某一个点的贡献相当于求前缀和;
实际上我维护的是公路条数,本质一样
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=300000;
const int inf=1000000000;
int n,m;
int cntedge;
int head[maxn];
int nex[maxn<<1],to[maxn<<1];
int addedge(int x,int y){
nex[++cntedge]=head[x];
to[cntedge]=y;
head[x]=cntedge;
}
int idx[maxn],father[maxn],siz[maxn];
int depth[maxn];
int temp;
int dfs(int now,int fa){
depth[now]=depth[fa]+1;
father[now]=fa;
idx[now]=(++temp);
siz[now]=1;
for(int i=head[now];i;i=nex[i]){
if(to[i]==fa)continue;
dfs(to[i],now);
siz[now]+=siz[to[i]];
}
}
int f[maxn][21];
int Lcainit(){
for(int i=1;i<=n;++i)f[i][0]=father[i];
for(int j=1;j<=20;++j){
for(int i=1;i<=n;++i){
f[i][j]=f[f[i][j-1]][j-1];
}
}
}
int Getlca(int u,int v){
if(depth[u]<depth[v])swap(u,v);
for(int j=20;j>=0;--j){
if(depth[f[u][j]]>=depth[v])u=f[u][j];
}
if(u==v)return u;
for(int j=20;j>=0;--j){
if(f[u][j]!=f[v][j]){
u=f[u][j];
v=f[v][j];
}
}
return father[u];
}
int c[maxn];
inline int lowbit(int x){
return x&(-x);
}
int add(int x,int val){
while(x<=n){
c[x]+=val;
x+=lowbit(x);
}
}
int query(int x){
int ret=0;
while(x){
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n-1;++i){
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
scanf("%d",&m);
m=n+m-1;
while(m--){
char opty=getchar();
while((opty!=‘W‘)&&(opty!=‘A‘))opty=getchar();
int x,y;
if(opty==‘A‘){
scanf("%d%d",&x,&y);
if(depth[x]>depth[y])swap(x,y);
add(idx[y],1);
add(idx[y]+siz[y],-1);
}else{
scanf("%d",&x);
printf("%d\n",depth[x]-1-query(idx[x]));
}
}
return 0;
}