一个字符串能重排成回文串等价于这个字符串最多只有一个字符出现次数为奇数次
这题的询问和子树中深度有关,那么显然可以用dsu on tree解决
把询问离线下来挂在点上,然后按dsu on tree的顺序统计子树信息即可
复杂度(O(nlogn+26m))
1 #include<bits/stdc++.h> 2 #define maxn 500005 3 using namespace std; 4 int n,m; 5 char s[maxn]; 6 vector<int> g[maxn]; 7 int sz[maxn],wson[maxn],d[maxn]; 8 void dfs(int u) 9 { 10 sz[u]=1; 11 for(int v:g[u]) 12 { 13 d[v]=d[u]+1; 14 dfs(v); 15 sz[u]+=sz[v]; 16 if(sz[v]>sz[wson[u]])wson[u]=v; 17 } 18 } 19 int has[maxn][26]; 20 vector<pair<int,int>> qry[maxn]; 21 int Ans[maxn]; 22 void add(int u,int x) 23 { 24 has[d[u]][s[u]-'a']+=x; 25 for(int v:g[u])add(v,x); 26 } 27 void solve(int u) 28 { 29 has[d[u]][s[u]-'a']++; 30 for(int v:g[u])if(v!=wson[u]) 31 { 32 solve(v); 33 add(v,-1); 34 } 35 if(wson[u])solve(wson[u]); 36 for(int v:g[u])if(v!=wson[u])add(v,1); 37 for(auto pa:qry[u]) 38 { 39 int dep=pa.first,id=pa.second; 40 int num=0; 41 for(int j=0;j<26;++j)if(has[dep][j]&1)num++; 42 if(num<=1)Ans[id]=1;else Ans[id]=0; 43 } 44 } 45 int main() 46 { 47 scanf("%d%d",&n,&m); 48 for(int x,i=2;i<=n;++i) 49 { 50 scanf("%d",&x); 51 g[x].push_back(i); 52 } 53 scanf("%s",s+1); 54 for(int i=1;i<=m;++i) 55 { 56 int u,x; 57 scanf("%d%d",&u,&x); 58 qry[u].push_back(make_pair(x,i)); 59 } 60 d[1]=1;dfs(1); 61 solve(1); 62 for(int i=1;i<=m;++i)if(Ans[i])puts("Yes");else puts("No"); 63 }