CF208E Blood Cousins(树上启发式合并)
转化题目,题目要求的是K级祖先,我们可以对于每个询问先跳到祖先,那么就是求对于这个祖先,depth[u]+k的个数是多少个,然后-1就是答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; int rt,f[N][25]; int depth[N],sz[N],son[N]; vector<pll> num[N]; int h[N],ne[N],e[N],idx; int res[N]; int ans[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs1(int u,int fa){ depth[u]=depth[fa]+1; f[u][0]=fa; int i; for(i=1;i<=21;i++){ f[u][i]=f[f[u][i-1]][i-1]; } sz[u]=1; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; dfs1(j,u); sz[u]+=sz[j]; if(sz[j]>sz[son[u]]){ son[u]=j; } } } int flag; void cal(int u,int fa,int x){ res[depth[u]]+=x; int i,j; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa||j==flag) continue; cal(j,u,x); } } void dfs(int u,int fa,int keep){ int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa||j==son[u]) continue; dfs(j,u,0); } if(son[u]){ dfs(son[u],u,1); flag=son[u]; } cal(u,fa,1); flag=0; for(i=0;i<num[u].size();i++){ auto x=num[u][i]; ans[x.first]=res[x.second]-1; //cout<<x.first<<" hhjjj "<<res[x.second]<<" "<<x.second<<endl; } //res[depth[u]]++; if(!keep){ cal(u,fa,-1); } } int vis[N]; int main(){ ios::sync_with_stdio(false); int i,j; int n,m; memset(h,-1,sizeof h); cin>>n; for(i=1;i<=n;i++){ int x; cin>>x; if(x!=0){ vis[i]=1; add(x,i); } } for(i=1;i<=n;i++){ if(!vis[i]) dfs1(i,0); } cin>>m; for(j=1;j<=m;j++){ int x,y; cin>>x>>y; int flag=0; int tmp=y; for(int i=20;i>=0;i--){ if(f[x][i]&&y>=(1<<i)){ y-=(1<<i); x=f[x][i]; } } if(y){ ans[i]=0; continue; } //cout<<x<<" gg "<<depth[x]+tmp<<endl; num[x].push_back({j,depth[x]+tmp}); } for(i=1;i<=n;i++){ if(!vis[i]){ dfs(i,0,0); //flag=0; } } for(i=1;i<=m;i++){ cout<<ans[i]<<" "; } cout<<endl; return 0; }
没有人不辛苦,只有人不喊疼