# [Apio2012]dispatching 主席树+dfs序 或 左偏树

Description

Sample Input
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1

Sample Output
6

#include <cstdio>
#include <cstring>

using namespace std;
typedef long long LL;
LL _max(LL x, LL y) {return x > y ? x : y;}
LL _min(LL x, LL y) {return x < y ? x : y;}

struct edge {
int x, y, next;
} e[210000]; int len, last[110000];
struct node {
int lc, rc;
LL c, sum;
} t[30 * 110000]; int cnt, rt[110000];
int id, ll[110000], rr[110000];
int a[110000], c[110000];

void ins(int x, int y) {
e[++len].x = x; e[len].y = y;
e[len].next = last[x]; last[x] = len;
}

void Link(int &u, int l, int r, int p, int c) {
if(!u) u = ++cnt;
t[u].c++; t[u].sum += c;
if(l == r) return ;
int mid = (l + r) / 2;
if(p <= mid) Link(t[u].lc, l, mid, p, c);
else Link(t[u].rc, mid + 1, r, p, c);
}

void Merge(int &u1, int u2) {
if(!u1 || !u2) {u1 = u1 + u2; return ;}
t[u1].c += t[u2].c; t[u1].sum += t[u2].sum;
Merge(t[u1].lc, t[u2].lc);
Merge(t[u1].rc, t[u2].rc);
}

LL query(int u1, int u2, int l, int r, LL s) {
if(l == r) return _min(t[u2].c - t[u1].c, s / l);
LL c = t[t[u2].lc].sum - t[t[u1].lc].sum;
int k = t[t[u2].lc].c - t[t[u1].lc].c;
int mid = (l + r) / 2;
if(c > s) return query(t[u1].lc, t[u2].lc, l, mid, s);
else return k + query(t[u1].rc, t[u2].rc, mid + 1, r, s - c);
}

void dfs(int x, int fa) {
ll[x] = ++id;
for(int k = last[x]; k; k = e[k].next) {
int y = e[k].y;
if(fa != y) dfs(y, x);
}
rr[x] = id;
}

int main() {
int n, m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
int x; scanf("%d%d%d", &x, &c[i], &a[i]);
ins(x, i); ins(i, x);
} dfs(1, 0);
for(int i = 1; i <= n; i++) {
int x = ll[i];
}
for(int i = 1; i <= n; i++) Merge(rt[i], rt[i - 1]);
LL ans = 0;
for(int i = 1; i <= n; i++) {
LL hh = query(rt[ll[i] - 1], rt[rr[i]], 1, 1000000000, m);
ans = _max(ans, hh * a[i]);
}
printf("%lld\n", ans);
return 0;
}

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
LL _max(LL x, LL y) {return x > y ? x : y;}

struct edge {
int x, y, next;
} e[110000]; int len, last[110000];
struct node {
int lc, rc, c, h;
} t[110000]; int cnt;
int a[110000], b[110000], rt[110000], tot[110000], M;
LL sum[110000], ans;

void ins(int x, int y) {
e[++len].x = x; e[len].y = y;
e[len].next = last[x]; last[x] = len;
}

int Merge(int u1, int u2) {
if(!u1 || !u2) return u1 + u2;
if(a[u1] < a[u2]) swap(u1, u2);
t[u1].rc = Merge(t[u1].rc, u2);
if(t[t[u1].lc].h < t[t[u1].rc].h) swap(t[u1].lc, t[u1].rc);
t[u1].h = t[t[u1].rc].h + 1;
return u1;
}

void dfs(int x) {
sum[x] = a[x]; tot[x] = 1;
for(int k = last[x]; k; k = e[k].next) {
int y = e[k].y;
dfs(y);
rt[x] = Merge(rt[x], rt[y]);
sum[x] += sum[y]; tot[x] += tot[y];
while(sum[x] > M && tot[x]) {
tot[x]--;
sum[x] -= a[rt[x]];
rt[x] = Merge(t[rt[x]].lc, t[rt[x]].rc);
}
}
ans = _max(ans, (LL)tot[x] * b[x]);
}

int main() {
int n; scanf("%d%d", &n, &M);
for(int i = 1; i <= n; i++) {
int x; scanf("%d%d%d", &x, &a[i], &b[i]);
ins(x, i);
}
for(int i = 1; i <= n; i++) rt[i] = i;
dfs(1);
printf("%lld\n", ans);
return 0;
}