一、題目
二、解法
可並堆板題,我們維護一個大根堆,每次把兒子的堆併到父親上去,然後用父親的領導力乘上最多選的個數來更新答案,容易發現如果一個堆中的元素和超過了,那麼直接刪去最大值,當前最大值不會用,以後更不會用,時間複雜度。
#include <cstdio>
#include <iostream>
using namespace std;
#define ll long long
const int M = 100005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,ch[M][2],val[M],dis[M],rt[M],fa[M],l[M],siz[M];
ll ans,sum[M];
int merge(int x,int y)
{
if(!x || !y) return x|y;
if(val[x]<val[y]) swap(x,y);
ch[x][1]=merge(ch[x][1],y);
if(dis[ch[x][0]]<dis[ch[x][1]]) swap(ch[x][0],ch[x][1]);
dis[x]=dis[ch[x][1]]+1;
return x;
}
int main()
{
dis[0]=-1;
n=read();m=read();
for(int i=1;i<=n;i++)
{
fa[i]=read();val[i]=read();l[i]=read();
siz[i]=1;ans=max(ans,1ll*l[i]);
sum[i]=val[i];rt[i]=i;
}
for(int i=n;i>1;i--)
{
int f=fa[i];
rt[f]=merge(rt[i],rt[f]);
siz[f]+=siz[i];sum[f]+=sum[i];
while(sum[f]>m)
{
sum[f]-=val[rt[f]];
rt[f]=merge(ch[rt[f]][0],ch[rt[f]][1]);
siz[f]--;
}
ans=max(ans,1ll*l[f]*siz[f]);
}
printf("%lld\n",ans);
}