洛谷題目傳送門
部落格園可能食用更佳
題目大意:
給定一棵權值為 \(0\) 或 \(1\) 的樹,\(n\) 個點,\(q\) 次操作:
-
0 i
把結點 \(i\) 的權值取反; -
1 i j
詢問點 \(i\) 到點 \(j\) 的最短路徑上權值是否全為 \(0\) 或全為 \(1\)。
題目分析:
樹上操作,看了下操作發現是樹剖板子題。
開一棵線段樹,操作一單點取反,考慮維護懶標記 \(tag\) 記錄結點的取反狀態即可,操作二求一下路徑上權值總和,再與最短路徑長度比較一下即可。
時間複雜度:\(\mathcal O(q \log n)\)。
Code:
#include<bits/stdc++.h>
#define ls u<<1
#define rs u<<1|1
#define il inline
#define pb push_back
using namespace std;
il int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48),ch=getchar();}return x*f;}
il char getc(){char ch=getchar();while(ch=='\n'||ch=='\r'||ch==' ')ch=getchar();return ch;}
const int N=3e5+5;
int n,q,a[N];
vector<int> g[N];
int fa[N],dep[N],siz[N],hs[N];
void dfs1(int u,int fath)
{
fa[u]=fath,dep[u]=dep[fath]+1;
siz[u]=1,hs[u]=-1;
for(auto v:g[u])
{
if(v==fath) continue;
dfs1(v,u),siz[u]+=siz[v];
if(hs[u]==-1||siz[v]>siz[hs[u]]) hs[u]=v;
}
}
int cnt,top[N],w[N],pos[N];
void dfs2(int u,int t)
{
top[u]=t,pos[w[u]=++cnt]=u;
if(~hs[u]) dfs2(hs[u],t);
for(auto v:g[u])
if(v^hs[u]&&fa[u]^v) dfs2(v,v);
}
int t[N<<2],tag[N<<2];
void push_up(int u) {t[u]=t[ls]+t[rs];}
void build(int u,int l,int r)
{
if(l==r) return t[u]=a[pos[l]],void();
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
push_up(u);
}
void push_down(int u,int l,int r)
{
if(!tag[u]) return;
tag[ls]^=1,tag[rs]^=1;
int mid=(l+r)>>1;
t[ls]=mid-l+1-t[ls],t[rs]=r-mid-t[rs];
tag[u]=0;
}
void update(int u,int l,int r,int x,int y)
{
if(y<l||r<x) return;
if(x<=l&&r<=y) return tag[u]^=1,t[u]=r-l+1-t[u],void();
push_down(u,l,r);
int mid=(l+r)>>1;
if(x<=mid) update(ls,l,mid,x,y);
if(y>mid) update(rs,mid+1,r,x,y);
push_up(u);
}
int query(int u,int l,int r,int x,int y)
{
if(y<l||r<x) return 0;
if(x<=l&&r<=y) return t[u];
push_down(u,l,r);
int mid=(l+r)>>1,res=0;
if(x<=mid) res+=query(ls,l,mid,x,y);
if(y>mid) res+=query(rs,mid+1,r,x,y);
return res;
}
bool range_query(int u,int v)
{
int ans=0,sum=0;
while(top[u]^top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans+=query(1,1,n,w[top[u]],w[u]);
sum+=w[u]-w[top[u]]+1;
u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
ans+=query(1,1,n,w[v],w[u]);
sum+=w[u]-w[v]+1;
return !ans||ans==sum;
}
int main()
{
n=read(),q=read();
for(int i=1;i<=n;i++) a[i]=getc()^48;
for(int i=1;i<n;i++)
{
int u=read()+1,v=read()+1;
g[u].pb(v),g[v].pb(u);
}
dfs1(1,0),dfs2(1,1),build(1,1,n);
while(q--)
{
int opt=read(),x=read()+1,y;
if(opt&1) y=read()+1,puts(range_query(x,y)?"YES":"NO");
else update(1,1,n,w[x],w[x]);
}
return 0;
}