rt,#1在本地过,在洛谷上显示第9行输出 “Yes”
思路大致是这样,边树链剖分,每条边权值0/1表示有没有战争,把路径上所有的权值或后1输出“No”,0输出“Yes”
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define lc tr[i].ch[0]
#define rc tr[i].ch[1]
#define mid (l+r)/2
using namespace std;
const int N=3e5;
vector<int>E[N+5];
int dep[N+5],sz[N+5],son[N+5],fa[N+5];
void dfs1(int u,int f){
dep[u]=dep[f]+1;
sz[u]=1;
fa[u]=f;
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(v==f)
continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]])
son[u]=v;
}
}
int id[N+5],rev[N+5],top[N+5],tot;
void dfs2(int u,int t){
id[u]=++tot;
rev[tot]=u;
top[u]=t;
if(!son[u])
return;
dfs2(son[u],t);
for(int i=0;i<E[u].size();i++){
int v=E[u][i];
if(v==son[u]||v==fa[u])
continue;
dfs2(v,v);
}
}
struct segTree{
int ch[2];
bool sum;
}tr[4*N+5];
int cnt,root;
void pushup(int i){
tr[i].sum=tr[lc].sum|tr[rc].sum;
}
void build(int &i,int l,int r){
i=++cnt;
if(l==r){
tr[i].sum=0;
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(i);
}
void update(int i,int l,int r,int x,int val){
if(l==r){
tr[i].sum=val;
return;
}
if(x<=mid)
update(lc,l,mid,x,val);
else
update(rc,mid+1,r,x,val);
pushup(i);
}
bool query(int i,int l,int r,int L,int R){
if(L<=l&&R>=r)
return tr[i].sum;
bool res=0;
if(L<=mid)
res|=query(lc,l,mid,L,R);
if(R>mid)
res|=query(rc,mid+1,r,L,R);
return res;
}
int n;
bool queryQuery(int u,int v){
bool res=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])
swap(u,v);
res|=query(root,1,n,id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
if(u!=v)
res|=query(root,1,n,id[u]+1,id[v]);
return res;
}
void queryChange(int x){
update(root,1,n,id[x],1);
}
void queryEnd(int x){
update(root,1,n,id[x],0);
}
int rec[N+5];
int main(){
//freopen("travian.in","r",stdin);
//freopen("travian.out","w",stdout);
int m;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
E[v].push_back(u);
}
dfs1(1,0);
dfs2(1,1);
build(root,1,n);
int sum=0;
for(int i=1;i<=m;i++){
char opt=getchar();
opt=getchar();
int p,q,x;
switch(opt){
case 'Q':
scanf("%d%d",&p,&q);
if(queryQuery(p,q))
printf("No\n");
else
printf("Yes\n");
break;
case 'C':
scanf("%d%d",&p,&q);
if(dep[p]>dep[q])
x=p;
else
x=q;
queryChange(x);
rec[++sum]=x;
break;
case 'U':
scanf("%d",&x);
x=rec[x];
queryEnd(x);
break;
}
}
return 0;
}