能成为回文串的显然是数量为奇数的字母小于2个。问题转化成求范围内点中各种字母总个数。
把询问离线处理,按照层数排序,就可以把每一层分开处理了。剩下的问题就是处理子树。
如果能构造出一个序列使同一棵子树的节点都连续在一起。就可以转化为一个区间查询问题。DFS对节点的访问顺序刚好满足这个性质。
在DFS过程中对每个节点重新标号,并对于每个节点,记录进入该节点时的最大标号(就是自己的标号)和出该节点的最大标号。 在区间查询时这两个标号间的所有点都在这个点的子树中。 同时用dv[i]记录第i层的所有点。
用树状数组做单点修改区间查询。每处理完一层,就把这一层的点还原,然后处理下一层。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #include <set> #include <cmath> #define LL long long #define maxn 500005 #include <vector> int N,M; int num[maxn]; int fa[maxn]; int cnt=0; int hs[maxn]; int sh[maxn]; int l[maxn],r[maxn]; vector <int> G[maxn]; vector <int> dv[maxn]; int idx(char c){ return c-'a'; } struct node{ int id,pa,dept; }Q[maxn]; bool res[maxn]; int c[30][maxn]; bool cmp(node a,node b){ return a.dept<b.dept; } int lowbit(int n) { return n&(-n); } int sum(int x,int k){ int res=0; while(x){ res+=c[k][x]; x-=lowbit(x); } return res; } void update(int x,int v,int k){ while(x<=N){ c[k][x]+=v; x+=lowbit(x); } } void dfs(int x,int dep){ cnt++; hs[cnt]=x; sh[x]=cnt; l[sh[x]]=cnt; dv[dep].push_back(cnt); for(int i=0;i<G[x].size();i++){ dfs(G[x][i],dep+1); } r[sh[x]]=cnt; } bool check(int n){ int nm=0; int ql=l[sh[Q[n].pa]],qr=r[sh[Q[n].pa]]; for(int i=0;i<26;i++){ int k=sum(qr,i)-sum(ql-1,i); if(k&1) nm++; } if(nm>1) return 0; return 1; } int main(){ scanf("%d%d",&N,&M); for(int i=2;i<=N;i++){ int p; scanf("%d",&p); G[p].push_back(i); } char s[maxn]; scanf("%s",s); for(int i=0;i<N;i++){ num[i+1]=idx(s[i]); } for(int i=0;i<M;i++){ scanf("%d%d",&Q[i].pa,&Q[i].dept); Q[i].id=i; } sort(Q,Q+M,cmp); dfs(1,1); int d=Q[0].dept; for(int i=0;i<dv[d].size();i++){ int cur=hs[dv[d][i]]; update(dv[d][i],1,num[cur]); } res[Q[0].id]=check(0); for(int i=1;i<M;i++){ if(Q[i].dept!=Q[i-1].dept){ int dp=Q[i-1].dept; for(int j=0;j<dv[dp].size();j++){ int cur=hs[dv[dp][j]]; update(dv[dp][j],-1,num[cur]); } dp=Q[i].dept; for(int j=0;j<dv[dp].size();j++){ int cur=hs[dv[dp][j]]; update(dv[dp][j],1,num[cur]); } } res[Q[i].id]=check(i); } for(int i=0;i<M;i++){ if(res[i]) printf("Yes\n"); else printf("No\n"); } } /* 7 3 1 1 2 2 3 3 abbcddc 1 3 2 3 3 3 */