[Apio2012]dispatching
题目
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。
1 ≤N ≤ 100,000 忍者的个数;
1 ≤M ≤ 1,000,000,000 薪水总预算;
0 ≤Bi < i 忍者的上级的编号
1 ≤Ci ≤ M 忍者的薪水;
1 ≤Li ≤ 1,000,000,000 忍者的领导力水平。
INPUT
从标准输入读入数据。
第一行包含两个整数 N和 M,其中 N表示忍者的个数,M表示薪水的总预算。
接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力。Master满足B i = 0,并且每一个忍者的老板的编号一定小于自己的编号
OUTPUT
输出一个数,表示在预算内顾客的满意度的最大值。
SAMPLE
INPUT
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1OUTPUT
6
解题报告
题面粘过来有毒qwq
我们考虑维护树上每个节点的权值和,并使得被选中的点最多,所以我们考虑对每个点维护一个大根堆,不断$pop$堆顶直到全堆得权值和小于限制即可
由于需要合并子树的堆,所以就变成了左偏树裸题了qwq
1 /************************************************************** 2 Problem: 2809 3 User: MAFIA 4 Language: C++ 5 Result: Accepted 6 Time:1444 ms 7 Memory:9936 kb 8 ****************************************************************/ 9 10 #include <iostream> 11 #include <cstring> 12 #include <cstdio> 13 using namespace std; 14 #define int long long 15 inline int read(){ 16 int sum(0);char ch(getchar()); 17 for(;ch<'0'||ch>'9';ch=getchar()); 18 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 19 return sum; 20 } 21 #define get_dis(x) (x?x->dis:-1) 22 #define get_sum(x) (x?x->sum:0) 23 #define get_size(x) (x?x->size:0) 24 struct node{ 25 node *lch,*rch; 26 int key,sum,dis,size; 27 node(int x=0):lch(NULL),rch(NULL),key(x),sum(x),dis(0),size(1){} 28 inline void pushup(){ 29 if(get_dis(this->lch)<get_dis(this->rch)) 30 swap(this->lch,this->rch); 31 this->dis=get_dis(this->rch)+1; 32 this->size=get_size(this->lch)+get_size(this->rch)+1; 33 this->sum=get_sum(this->lch)+get_sum(this->rch)+this->key; 34 } 35 }*heap[100005]; 36 inline node* merge(node *&x,node *&y){ 37 if(!x)return y;if(!y)return x; 38 if(x->key<y->key)swap(x,y); 39 x->rch=merge(x->rch,y); 40 x->pushup(); 41 return x; 42 } 43 inline void insert(node *&x,int v){ 44 node *tmp(new node(v)); 45 x=merge(x,tmp); 46 } 47 inline node* pop(node *&x){ 48 if(!x)return NULL; 49 return merge(x->lch,x->rch); 50 } 51 struct edge{ 52 int e; 53 edge *n; 54 }*pre[100005]; 55 inline void insert(int s,int e){ 56 edge *tmp(new edge); 57 tmp->e=e;tmp->n=pre[s];pre[s]=tmp; 58 } 59 int n,m,root; 60 long long ans,l[100005]; 61 inline void dfs(int u){ 62 for(edge *i=pre[u];i;i=i->n){ 63 int e(i->e);dfs(e); 64 heap[u]=merge(heap[u],heap[e]); 65 } 66 while(heap[u]&&heap[u]->sum>m) 67 heap[u]=pop(heap[u]); 68 ans=max(ans,1ll*get_size(heap[u])*l[u]); 69 } 70 signed main(){ 71 // freopen("dispatching.in","r",stdin);freopen("dispatching.out","w",stdout); 72 n=read(),m=read(); 73 for(int i=1;i<=n;++i){ 74 int x(read()),y(read()),z(read()); 75 if(!x)root=i; 76 else insert(x,i); 77 insert(heap[i],y);l[i]=z; 78 } 79 dfs(root);printf("%lld",ans); 80 }