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;
}