codeforces 570D

一个字符串能重排成回文串等价于这个字符串最多只有一个字符出现次数为奇数次

这题的询问和子树中深度有关,那么显然可以用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 }
View Code

猜你喜欢

转载自www.cnblogs.com/uuzlove/p/12290409.html