B. Alyona and a tree(树上差分&倍增)
倍增找到结点 u u u的最远祖先结点 v v v, d i s ( u , v ) ≤ a u dis(u,v)\le a_u dis(u,v)≤au 。
该条链都+1,这一步差分实现,然后求下前缀和就是答案了。
// Problem: B. Alyona and a tree
// Contest: Codeforces - Codeforces Round #381 (Div. 1)
// URL: https://codeforces.ml/problemset/problem/739/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-08-03 16:55:53
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}
int f[N][21],h[N],cnt,a[N];
ll d[N];
struct edge{
int to,nt,w;
}e[N<<1];
int n,mx;
#define il inline
il void add(int u,int v,int w){
e[++cnt]={v,h[u],w},h[u]=cnt;
}
void dfs(int u,int fa){
f[u][0]=fa;
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to,w=e[i].w;
d[v]=d[u]+w;
dfs(v,u);
}
}
void init(){
for(int j=1;j<=mx;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
int dif[N];
void fun(int u){
int v=u;
for(int i=mx;~i;i--){
if(f[v][i]&&d[u]-d[f[v][i]]<=a[u]) v=f[v][i];
}
if(u!=1) dif[f[u][0]]++;
if(v!=1) dif[f[v][0]]--;
}
ll dfs1(int u){
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to;
dif[u]+=dfs1(v);
}
return dif[u];
}
int main(){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);
mx=(int)log2(n)+1;
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);add(u,i+1,v);
}
dfs(1,0);
init();
for(int i=1;i<=n;i++) fun(i);
dfs1(1);
for(int i=1;i<=n;i++) printf("%d ",dif[i]);printf("\n");
return 0;
}