1. 程式人生 > 實用技巧 >【CF570D】Tree Requests【dsu on tree】

【CF570D】Tree Requests【dsu on tree】

傳送門

Solution

一些字母能形成迴文串的充要條件是出現奇數次的字母數量\(\le 1\),於是直接維護\(w[i][j]\)表示深度為\(i\)的點鐘,字母\(j\)出現的次數即可:
dsu on tree

Code

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int n,m,c[N],cnt,first[N],ans[N];
struct node{
	int v,nxt;
}e[N<<1];
vector<pair<int,int> > que[N];
inline void add(int u,int v){e[++cnt].v=v;e[cnt].nxt=first[u];first[u]=cnt;}
char s[N];
int dep[N],hson[N],siz[N],w[N][26],son;
inline void dfs(int u,int f){
	dep[u]=dep[f]+1;siz[u]=1;
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==f) continue;
		dfs(v,u);siz[u]+=siz[v];
		if(siz[v]>siz[hson[u]]) hson[u]=v;
	}
}
inline void work(int u,int f,int tp){
	w[dep[u]][c[u]]+=tp;
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==f||v==son) continue;
		work(v,u,tp);
	}
}
inline void dsu(int u,int f,int tp){
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==f||v==hson[u]) continue;
		dsu(v,u,0); 
	}
	if(hson[u]) dsu(hson[u],u,1),son=hson[u];
	work(u,f,1);son=0;
	for(int i=0;i<que[u].size();++i){
		int d=que[u][i].first,q=que[u][i].second;
		int cnt1=0,cnt2=0;
		for(int j=0;j<=25;++j)
			w[d][j]&1?cnt1++:cnt2++;
		ans[q]=cnt1<=1;
	}
	if(!tp) work(u,f,-1);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=2,f;i<=n;++i)
		scanf("%d",&f),add(f,i);
	scanf("%s",s+1);
	for(int i=1;i<=n;++i)
		c[i]=s[i]-'a';
	for(int i=1,a,b;i<=m;++i){
		scanf("%d%d",&a,&b);
		que[a].push_back(make_pair(b,i));
	}
	dfs(1,0);
	dsu(1,0,1);
	for(int i=1;i<=m;++i) puts(ans[i]?"Yes":"No");
	return 0;
}