【CF570D】Tree Requests【dsu on tree】
阿新 • • 發佈:2021-01-09
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; }