考虑倒着想 每次弹出最大值知道费用<=M 然后向上合并
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void read(ll &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; inline int ran() { static int x=31253125;x+=(x<<4)+1;return x&65536; } struct node{node *l,*r;ll key;}nodes[N]; node *M(node *p,node *q) { return (!p||!q)?(p?p:q):(p->key<q->key?M(q,p):((ran()?p->l=M(p->l,q):p->r=M(p->r,q)),p)); } int n,Me; node *root[N]; int fat[N],tot[N],deg[N]; ll sum[N],L[N]; int Stack[N],pnt; ll ans; int main() { ll x; int s; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(Me); for (int i=1;i<=n;i++) { read(fat[i]); deg[fat[i]]++; read(x); nodes[i].key=x; nodes[i].l=nodes[i].r=NULL; sum[i]=x; tot[i]=1; root[i]=nodes+i; read(L[i]); } for (int i=1;i<=n;i++) if (!deg[i]) Stack[++pnt]=i; while (pnt){ s=Stack[pnt--]; while (root[s] && sum[s]>Me) sum[s]-=root[s]->key,tot[s]--,root[s]=M(root[s]->l,root[s]->r); ans=max(ans,tot[s]*L[s]); if (fat[s]) { root[fat[s]]=M(root[fat[s]],root[s]); sum[fat[s]]+=sum[s]; tot[fat[s]]+=tot[s]; if (!(--deg[fat[s]])) Stack[++pnt]=fat[s]; } } printf("%lld\n",ans); return 0; }