注释是处理空节点的部分,这份代码可以AC
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-f;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void work(int k){
if(k<0){
putchar('-');
k=-k;
}
if(k>9)
work(k/10);
putchar(k%10+'0');
}
int n,m,cnt,first[50005],s[50005],son[50005],fa[50005],dp[50005],id[50005],rev[50005],dep[50005],tot,c[50005][2],d[2];
struct q1{
int u,w,nex;
}a[100005];
void add(int u1,int w1){
a[++cnt]={u1,w1,first[u1]};
first[u1]=cnt;
}
void dfs(int u,int dad){
fa[u]=dad;
s[u]=1;
dep[u]=dep[dad]+1;
for(int i=first[u];i;i=a[i].nex){
if(a[i].w==dad)
continue;
dfs(a[i].w,u);
s[u]+=s[a[i].w];
if(s[son[u]]<s[a[i].w])
son[u]=a[i].w;
}
}
void dfs2(int u,int t){
dp[u]=t;
id[u]=++tot;
rev[tot]=u;
if(!son[u])
return ;
dfs2(son[u],t);
for(int i=first[u];i;i=a[i].nex){
if(a[i].w==fa[u]||a[i].w==son[u])
continue;
dfs2(a[i].w,a[i].w);
}
}
struct node{
int lx[2],rx[2],dis[2][2];
inline void init(){
memset(lx,0,sizeof(lx));
memset(rx,0,sizeof(rx));
memset(dis,0,sizeof(dis));
}
}tree[200005];
inline node operator +(node x,node y){//空节点合并的问题会出在dis
node a;
a.init();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
a.lx[i]=max({a.lx[i],x.lx[i],x.dis[i][j]+y.lx[j]});
a.rx[i]=max({a.rx[i],y.rx[i],y.dis[j][i]+x.rx[j]});
a.dis[i][j]=-1e9;
for(int k=0;k<2;k++){
a.dis[i][j]=max(a.dis[i][j],x.dis[i][k]+y.dis[k][j]);//如果这里x是空节点a.dis[i][j]只能由y.dis[i][j]转移,但是这里可能会由y.dis[i^1][j]转移过来,导致答案多算
}
}
}
return a;
}
void create(int k,int id){
tree[k].dis[0][0]=c[id][0]?c[id][0]:-1e9;
tree[k].lx[0]=tree[k].rx[0]=c[id][0];
tree[k].dis[1][1]=c[id][1]?c[id][1]:-1e9;
tree[k].lx[1]=tree[k].rx[1]=c[id][1];
tree[k].dis[0][1]=tree[k].dis[1][0]=(c[id][0]&&c[id][1])?c[id][0]+c[id][1]:-1e9;
}
void build(int k,int l,int r){
if(l==r){
create(k,rev[l]);
return ;
}
int mid=(l+r)>>1;
build(2*k,l,mid);
build(2*k+1,mid+1,r);
tree[k]=tree[2*k]+tree[2*k+1];
}
void change(int k,int l,int r,int x,int d[]){
if(l>x||r<x)
return ;
if(l==r&&l==x){
c[rev[l]][0]=d[0];
c[rev[l]][1]=d[1];
create(k,rev[l]);
return ;
}
int mid=(l+r)>>1;
change(2*k,l,mid,x,d);
change(2*k+1,mid+1,r,x,d);
tree[k]=tree[2*k]+tree[2*k+1];
}
node query(int k,int l,int r,int x,int y){
if(l>=x&&r<=y)
return tree[k];
int mid=(l+r)>>1;
if(mid<x)
return query(2*k+1,mid+1,r,x,y);
if(mid+1>y)
return query(2*k,l,mid,x,y);
return query(2*k,l,mid,x,y)+query(2*k+1,mid+1,r,x,y);//空节点合并会有问题,所以要分开写
}
int queried(int x,int y){
node ansx,ansy;
int flag=0,f=0;//处理空节点
ansx.init();
ansy.init();
while(dp[x]!=dp[y]){
if(dep[dp[x]]>dep[dp[y]]){
// if(!flag){
// flag=1;
// ansx=query(1,1,n,id[dp[x]],id[x]);
// }
// else
ansx=query(1,1,n,id[dp[x]],id[x])+ansx;
x=fa[dp[x]];
}
else{
// if(!f){
// f=1;
// ansy=query(1,1,n,id[dp[y]],id[y]);
// }
// else
ansy=query(1,1,n,id[dp[y]],id[y])+ansy;
y=fa[dp[y]];
}
}
if(dep[x]>dep[y]){
// if(flag)
ansx=query(1,1,n,id[y],id[x])+ansx;
// else{
// ansx=query(1,1,n,id[y],id[x]);
// flag=1;
// }
}
else{
// if(f)
ansy=query(1,1,n,id[x],id[y])+ansy;
// else{
// ansy=query(1,1,n,id[x],id[y]);
// f=1;
// }
}
swap(ansx.lx[0],ansx.rx[0]);
swap(ansx.lx[1],ansx.rx[1]);
swap(ansx.dis[0][1],ansx.dis[1][0]);
// if(!flag)
// ansx=ansy;
// else if(!f)
// ansx=ansx;
// else
ansx=ansx+ansy;
return max(ansx.lx[0],ansx.lx[1]);
}
int main(){
n=read();
m=read();
for(int i=1,x,y;i<n;i++){
x=read();
y=read();
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++){
char f;
for(int j=0;j<2;j++){
cin>>f;
c[i][j]=(f=='.');
}
}
dfs(1,0);
dfs2(1,1);
build(1,1,n);
while(m--){
char f;
int s,t;
cin>>f;
s=read();
if(f=='C'){
for(int i=0;i<2;i++){
char g;
cin>>g;
d[i]=(g=='.');
}
change(1,1,n,id[s],d);
}
else{
t=read();
work(queried(s,t));
puts("");
}
}
return 0;
}