只有我一个人纠结了半天没读懂题吗?心塞。就是给你一个关系子图,选一个点作为管理者,他可以派遣自己为根的这棵子树的所有的忍者,但是总费用不超过m,满意度等于派遣出去的忍者数目*管理力(自己也可以被自己派遣)。
首先考虑,如果选当前节点为管理者派遣的忍者费用已经超过了m,那么对于他的父亲节点,费用肯定也是不够的。所以每一次都要维护不超过m的忍者,基于贪心的思想,忍者的费用对答案无贡献只有数目有,所以简单的弹出费用最高的就好了,然后每次合并。
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 100020
#define LL long long
using namespace std;
int n,head[maxn],tot=1,root,size[maxn],rt[maxn];
LL l[maxn],c[maxn],m,ans,sum[maxn];
struct edge{int v,next;}e[maxn*2];
void adde(int a,int b){e[tot].v=b,e[tot].next=head[a];head[a]=tot++;}
struct rTree{
LL v[maxn];int ls[maxn],rs[maxn],d[maxn];
int merge(int x,int y){
if(x==0||y==0)return x+y;
if(v[x]<v[y])swap(x,y);
rs[x]=merge(rs[x],y);
if(d[rs[x]]>d[ls[x]])swap(ls[x],rs[x]);
d[x]=d[rs[x]]+1;
return x;
}
void pop(int& x){
x=merge(ls[x],rs[x]);
}
LL top(int x){
return v[x];
}
}q;
void dfs(int u){
sum[u]=c[u],size[u]=1,q.v[u]=c[u],rt[u]=u;
for(int v,i=head[u];i;i=e[i].next){
dfs(v=e[i].v);
rt[u]=q.merge(rt[u],rt[v]);
sum[u]+=sum[v],size[u]+=size[v];
}
while(sum[u]>m){
sum[u]-=q.top(rt[u]);
q.pop(rt[u]);size[u]--;
}
ans=max(ans,size[u]*l[u]);
}
int main(){
scanf("%d%lld",&n,&m);int a;
for(int i=1;i<=n;i++){
scanf("%d%lld%lld",&a,c+i,l+i);
if(a)adde(a,i);
else root=i;
}
dfs(root);
printf("%lld",ans);
return 0;
}