CF208E
跟上一题几乎是一模一样的套路。
离线+倍增预处理+开以深度为权值的线段树。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m,f[maxn][20];
int root[maxn],tot;
int dep[maxn];
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int beg[maxn],nex[maxn],to[maxn],e;
inline void add(int x,int y){
e++;nex[e]=beg[x];
beg[x]=e;to[e]=y;
}
inline void dfs(int x,int fa){
dep[x]=dep[fa]+1;
for(int i=1;i<=15;i++)
f[x][i]=f[f[x][i-1]][i-1];
for(int i=beg[x];i;i=nex[i])
dfs(to[i],x);
}
vector<pair<int,int> >q[maxn];
struct node{
int val,lc,rc;
}tr[maxn*20];
int rt[maxn],Max,cnt,ans[maxn];
inline int update(int h,int l,int r,int x){
if(!h)h=++cnt;
tr[h].val++;
if(l==r)return h;
int mid=(l+r)>>1;
if(mid>=x)tr[h].lc=update(tr[h].lc,l,mid,x);
else tr[h].rc=update(tr[h].rc,mid+1,r,x);
return h;
}
inline int merge(int a,int b,int l,int r){
if(!a)return b;
if(!b)return a;
tr[a].val+=tr[b].val;
if(l==r)return a;
int mid=(l+r)>>1;
tr[a].lc=merge(tr[a].lc,tr[b].lc,l,mid);
tr[a].rc=merge(tr[a].rc,tr[b].rc,mid+1,r);
return a;
}
inline int query(int h,int l,int r,int x){
if(l==r)return tr[h].val;
int mid=(l+r)>>1;
if(mid>=x)return query(tr[h].lc,l,mid,x);
else return query(tr[h].rc,mid+1,r,x);
}
inline void solve(int x,int fa){
rt[x]=update(rt[x],1,Max,dep[x]);
for(int i=beg[x];i;i=nex[i]){
int t=to[i];
solve(t,x);
rt[x]=merge(rt[x],rt[t],1,Max);
}
int a,b;
for(int i=0;i<q[x].size();i++){
a=q[x][i].first;b=q[x][i].second;
ans[b]=query(rt[x],1,Max,dep[x]+a)-1;
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
f[i][0]=read();
if(f[i][0])add(f[i][0],i);
else root[++tot]=i;
}
for(int i=1;i<=tot;i++)
dfs(root[i],0);
for(int i=1;i<=n;i++)
Max=max(Max,dep[i]);
m=read();
int x,y;
for(int i=1;i<=m;i++){
x=read(),y=read();
int tmp=dep[x]-y;
for(int j=15;j>=0;j--)
if(dep[f[x][j]]>=tmp)x=f[x][j];
q[x].push_back(make_pair(y,i));
}
for(int i=1;i<=tot;i++)
solve(root[i],0);
for(int i=1;i<=m;i++)
printf("%d ",ans[i]);
return 0;
}
手打一遍过……
深深地感到自己的弱小。