SP30785 ADAAPPLE - Ada and Apple 題解

lunjiahao發表於2024-11-02

洛谷題目傳送門

部落格園可能食用更佳

題目大意:

給定一棵權值為 \(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;
}

相關文章