处理下面三件事,所有的事件都是按照时间顺序给出的。
1.(Q p q)从第 p 个部落出发的建筑工人想知道能否到达第 q 个部落了,你要回答的便是(Yes/No),注意大小写
2.(C p q)第 p 个部落与第 q 个部落开战了,保证他们一定是相邻的部落,且目前处于停战(未开战)状态
3.(U x ) 第 x 次发生的战争结束了,它将永远的被载入史册,不复存在(保证这个消息不会告诉你多次)
对于30%的数据 1<=n,m<=6000
对于另30%的数据,保证部落之间的地理关系是一条链,且 i 与 i + 1 之间有一条道路
对于另30%的数据,1<=n,m<=100000
对于100%的数据,1<=n,m<=300000
一道很裸的树剖
但是数据太大卡线段树,用树状数组可以过
用树状数组维护一条链上是否有战争
这个思想可以树上差分
树状数组维护Sum(i)i到root的战争个数
询问Sum(p)+Sum(q)-Sum(Lca(p,q))*2
#include
#include
#include
#define N 300010
#define fr first
#define se second
#define mp(p,q) make_pair(p,q)
using namespace std;
pair<int,int>b[N<<1];
int num,h[N],d[N],fa[N],sz[N],son[N],top[N],tot,dfn[N],n,m,t[N],p,q,cnt,c[N];
char ch;
int rd(){
int x=0,y=1;
char ch;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')y=-1;
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*y;
}
int lb(int x){
return x&(-x);
}
void ljb(int p,int q){
b[++num]=mp(q,h[p]);
h[p]=num;
}
int Dfs(int x){
sz[x]=1;
for(int i=h[x],y=b[i].fr;i;i=b[i].se,y=b[i].fr)if(y!=fa[x]){
fa[y]=x;
d[y]=d[x]+1;
sz[x]+=Dfs(y);
if(sz[y]>sz[son[x]])son[x]=y;
}
return sz[x];
}
void dfs(int x){
if(x==son[fa[x]])top[x]=top[fa[x]];
else top[x]=x;
dfn[x]=++tot;
if(son[x])dfs(son[x]);
for(int i=h[x],y=b[i].fr;i;i=b[i].se,y=b[i].fr)if(y!=fa[x]&&y!=son[x])dfs(y);
}
void Ins(int x,int v){
for(int i=x;i<=n;i+=lb(i))t[i]+=v;
}
int Sum(int x){
int tmp=0;
for(int i=x;i>=1;i-=lb(i))tmp+=t[i];
return tmp;
}
bool Que(int p,int q){
while(top[p]!=top[q]){
if(dfn[top[p]]if(Sum(dfn[p])-Sum(dfn[top[p]]-1))return 1;
p=fa[top[p]];
}
if(dfn[p]return Sum(dfn[p])-Sum(dfn[q])?1:0;
}
int main(){
n=rd(),m=rd();
for(int i=1;i1),dfs(1);
// for(int i=1;i<=n;i++)printf("%d ",dfn[i]);
// printf("\n");
for(int i=1;i<=m;i++){
while((ch=getchar())!='C'&&ch!='Q'&&ch!='U');
if(ch=='C'){
p=rd(),q=rd();
if(dfn[p]1);
}
else if(ch=='Q'){
p=rd(),q=rd();
Que(p,q)?puts("No"):puts("Yes");
}
else {
p=rd();
Ins(dfn[c[p]],-1);
}
}
}
#include
#include
#include
#define N 300010
#define fr first
#define se second
#define mp(p,q) make_pair(p,q)
using namespace std;
pair<int,int>b[N<<1];
int num,h[N],d[N],fa[N],sz[N],son[N],top[N],tot,dfn[N],n,m,t[N],p,q,cnt,c[N];
char ch;
int rd(){
int x=0,y=1;
char ch;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')y=-1;
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*y;
}
int lb(int x){
return x&(-x);
}
void ljb(int p,int q){
b[++num]=mp(q,h[p]);
h[p]=num;
}
int Dfs(int x){
sz[x]=1;
for(int i=h[x],y=b[i].fr;i;i=b[i].se,y=b[i].fr)if(y!=fa[x]){
fa[y]=x;
d[y]=d[x]+1;
sz[x]+=Dfs(y);
if(sz[y]>sz[son[x]])son[x]=y;
}
return sz[x];
}
void dfs(int x){
if(x==son[fa[x]])top[x]=top[fa[x]];
else top[x]=x;
dfn[x]=++tot;
if(son[x])dfs(son[x]);
for(int i=h[x],y=b[i].fr;i;i=b[i].se,y=b[i].fr)if(y!=fa[x]&&y!=son[x])dfs(y);
}
void Ins(int x,int v){
for(int i=x;i<=n;i+=lb(i))t[i]+=v;
}
int Sum(int x){
int tmp=0;
for(int i=x;i>=1;i-=lb(i))tmp+=t[i];
return tmp;
}
bool Que(int p,int q){
while(top[p]!=top[q]){
if(dfn[top[p]]if(Sum(dfn[p])-Sum(dfn[top[p]]-1))return 1;
p=fa[top[p]];
}
if(dfn[p]return Sum(dfn[p])-Sum(dfn[q])?1:0;
}
int main(){
n=rd(),m=rd();
for(int i=1;i1),dfs(1);
// for(int i=1;i<=n;i++)printf("%d ",dfn[i]);
// printf("\n");
for(int i=1;i<=m;i++){
while((ch=getchar())!='C'&&ch!='Q'&&ch!='U');
if(ch=='C'){
p=rd(),q=rd();
if(dfn[p]1);
}
else if(ch=='Q'){
p=rd(),q=rd();
Que(p,q)?puts("No"):puts("Yes");
}
else {
p=rd();
Ins(dfn[c[p]],-1);
}
}
}