【CF208E】Blood Cousins【dsu on tree】
阿新 • • 發佈:2021-01-09
Solution
可以將詢問轉化為詢問點\(x\)的\(K\)級兒子有多少個
也就是\(x\)子樹內深度為\(dep[x]+k\)的點有多少個,
於是上dsu on tree就完了
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,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; } int dep[N],hson[N],siz[N],pa[N][20]; inline void dfs(int u,int f){ pa[u][0]=f;siz[u]=1; for(int i=1;i<=19;++i) pa[u][i]=pa[pa[u][i-1]][i-1]; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(v==f) continue; dep[v]=dep[u]+1; dfs(v,u); siz[u]+=siz[v]; if(siz[v]>siz[hson[u]]) hson[u]=v; } } inline int up(int u,int k){ for(int i=19;i>=0;--i) if(k&(1<<i)) u=pa[u][i]; return u; } int w[N],son; inline void work(int u,int f,int tp){ w[dep[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) ans[que[u][i].second]=w[que[u][i].first]-1; if(!tp) work(u,f,-1); } int main(){ scanf("%d",&n); for(int i=1,f;i<=n;++i){ scanf("%d",&f); if(!f) f=n+1; add(f,i); } scanf("%d",&m); dfs(n+1,0); for(int i=1,u,k;i<=m;++i){ scanf("%d%d",&u,&k); int x=up(u,k); if(x==n+1||x==0) continue; que[x].push_back(make_pair(dep[u],i)); } dsu(n+1,0,1); for(int i=1;i<=m;++i) printf("%d ",ans[i]); return 0; }