//题意:n个节点的树,每条边有边权,现在要求对于每一个结点u的子树中有多少个节点
// 满足到u点的距离不大于t
// 思路:树上差分思想还是比较好想到的,因为要满足dep[x]-dep[u]<=t,所以在x之上到
// u之间的所有点对u点的答案都有贡献,所以上差分就好
//
// 主要不是很熟练的的是如何对于每个询问求满足条件的x
// 1.第一种实现方法利用倍增,从节点u开始向下倍增(注意这里犯了一个很严重的错误,
// 我们以节点u为头向下倍增是不可行的,因为他会有多个儿子,也就是分叉。正确的
// 方法是对每一个x向上倍增,找满足条件的祖先节点)
//
// 这样可以在logn步的规模内
// 跳到x节点。因为我们需要在每个节点都进行一次倍增查询,所以总的复杂度是
// O(nlogn)。
//
//思路一
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
struct edge {
int len, to;
edge(int a = 0, int b = 0) {
len = a, to = b;
}
};
vector<edge> mp[N];
int n, t;
int lis[N][20], dep[N], ans[N];
void dfs(int x) {
for (auto y : mp[x]) {
if (y.to == lis[x][0]) continue;
dep[y.to] = dep[x] + y.len;
dfs(y.to);
}
}
void dfs2(int y) {//当前遍历节点
int x = y;
for (int i = 18; i >= 0; i--) {
if (lis[x][i] == 0) continue;
if (dep[lis[x][i]] + t < dep[y]) continue;
x = lis[x][i];
}
ans[y] += 1;
ans[lis[x][0]] -= 1;
for (auto w : mp[y]) {
if (w.to == lis[y][0]) continue;
dfs2(w.to);
ans[y] += ans[w.to];
}
}
signed main() {
cin >> n >> t;
for (int i = 2; i <= n; i++) {
int a, b; cin >> a >> b;
mp[i].push_back({ b,a });
mp[a].push_back({ b,i });
lis[i][0] = a;
}
for (int i = 1; i <= 18; i++) {
for (int j = 1; j <= n; j++) {
lis[j][i] = lis[lis[j][i - 1]][i - 1];
}
}
lis[1][0] = 0;
dfs(1); dep[1] = 0;
dfs2(1);
for (int i = 1; i <= n; i++)
cout << ans[i] << endl;
return 0;
}
/*
4 5
1 4
2 3
1 5
*/
//思路:类似于区间数点问题,就是先dfs求出每个点的dep,然后按dep降序排序,删除和插入就行,这里代码中详细讲,这个思路有点妙啊
//思路二
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, id[N], r[N], now, ans[N];
pair<long long, int> a[N];
struct BIT
{
int tree[N];
void modify(int x, int val)
{
for (; x <= n; x += x & -x)
tree[x] += val;
}
int query(int x)
{
int ans = 0;
for (; x; x -= x & -x)
ans += tree[x];
return ans;
}
}T;
//树状数组模板
vector<pair<int, long long>> mat[N];
void dfs(int k)
{
id[k] = ++now;
//dfs序
for (auto e : mat[k])
{
a[e.first] = make_pair(a[k].first + e.second, e.first);
dfs(e.first);
}
r[k] = now;
//结束时间戳
}
int main()
{
long long l;
cin >> n >> l;
for (int i = 2; i <= n; i++)
{
int p;
long long w;
cin >> p >> w;
mat[p].push_back(make_pair(i, w));
}
a[1] = make_pair(0ll, 1);
dfs(1);
sort(a + 1, a + n + 1);
int j = n;//j初始值为n,也就是最深
for (int i = n; i; i--)
{
for (; a[j].first - a[i].first > l; j--)
T.modify(id[a[j].second], -1);
//删除超过距离超过L的点
T.modify(id[a[i].second], 1);
//插入当前点
ans[a[i].second] = T.query(r[a[i].second]) - T.query(id[a[i].second] - 1);
//统计子树答案
}
//这里删点的逻辑很妙,因为我们按照dep的降序的话,i和j有两种情况
// 情况一:i和j是在同一条树链上的,那么dep[j]-dep[i]>l的话,j点是肯定要删除的
// 情况二:i和j没在同一条树链上,这个时候dep[j]-dep[i]>l我们也把j删除了,因为既然对于i来说j已经不满足条件了,那么
// 对于j这条树链上的其他点,j也无法做出贡献了(因为dep[其他点]<=dep[i])
//
for (int i = 1; i <= n; i++)
cout << ans[i] << endl;
return 0;
}