题目链接:codeforces570D
正解:$dsu$ $on$ $tree$
解题报告:
考虑这又是一类子树内的不带修改统计问题,直接上$dsu$ $on$ $tree$好咯。
直接按上一道题的做法做,类似地存一下每个深度每种字符的出现次数,对于每个点的询问,在每个点处查询一下就好了,只需奇数的个数$<=1$即可。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 500011; const int MAXM = 1000011; int n,m,ecnt,first[MAXN],to[MAXM],next[MAXM],Son,ans[MAXN]; int size[MAXN],son[MAXN],deep[MAXN],cnt[MAXN][26]; char ch[MAXN]; struct node{ int x,id; }tmp; vector<node>w[MAXN]; inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void dfs(int x,int fa){ size[x]=1; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa) continue; deep[v]=deep[x]+1; dfs(v,x); size[x]+=size[v]; if(size[v]>size[son[x]]) son[x]=v; } } inline void add(int x,int fa,int val){ cnt[ deep[x] ][ ch[x]-'a' ]+=val; for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa || v==Son) continue; add(v,x,val); } } inline void solve(int x,int fa,bool top){ for(int i=first[x];i;i=next[i]) { int v=to[i]; if(v==fa || v==son[x]) continue; solve(v,x,1); } if(son[x]) solve(son[x],x,0),Son=son[x]; add(x,fa,1); Son=0; //处理在x上的询问 for(int i=0,ss=w[x].size();i<ss;i++) { tmp=w[x][i]; if(tmp.x<deep[x]) { ans[tmp.id]=1; continue; } int cc=0,h=tmp.x; for(int j=0;j<26;j++) if(cnt[h][j]&1) cc++; if(cc>1) ans[tmp.id]=0; else ans[tmp.id]=1; } if(top) add(x,fa,-1); } inline void work(){ n=getint(); m=getint(); int x,y; for(int i=2;i<=n;i++) { x=getint(); link(x,i); } scanf("%s",ch+1); deep[1]=1; dfs(1,0); for(int i=1;i<=m;i++) { x=getint(); y=getint(); tmp.x=y; tmp.id=i; w[x].push_back(tmp); } solve(1,0,1); for(int i=1;i<=m;i++) if(ans[i]) puts("Yes"); else puts("No"); } int main() { work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。