BZOJ2809: [Apio2012]dispatching
Description
在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 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,并且每一个忍者的老板的编号一定小于自己的编号 Bi < i。
Output
输出一个数,表示在预算内顾客的满意度的最大值。
Sample Input
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
Sample Output
6
思路{
左偏树懂了,然而通过这道题还是可以发现并不熟练。
首先是很容易想到采用树形DP的方法向上合并解。
故想到使用可并堆。但是是大根堆还是小根堆?
若小根堆(我最开始写的),应当顺序统计,直到和大于m为止,其他全部pop
看出,这样的复杂度比较高。(然而我没有TLE,WA了。。。。。。。。)
大根堆的话,弹出元素直到元素和<=m.比较容易实现。
在DFS的过程中,为了防止变量之间的冲突,
还要设一个数组表示当前点所属的堆。(可能我就WA在这里吧。。。。)
为了在COGS上速度超过PZ,我竟然使用了读入优化。。。。。。
}
#include<bits/stdc++.h> #define RG register #define il inline #define N 100010 #define LL long long using namespace std; int v[N],l[N],r[N],d[N],L[N],n,head[N],tot,BL[N],sz[N];LL sum[N]; struct ed{int nxt,to;}e[N];int m;LL ans; void add(RG int u,RG int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;} il int merge(RG int x,RG int y){ if(!x||!y)return x+y; if(v[x]<v[y])swap(x,y); r[x]=merge(r[x],y); if(d[r[x]]>d[l[x]])swap(r[x],l[x]); d[x]=d[r[x]]+1;return x; } il int getint(){ int w=0;bool q=0; char c=getchar(); while((c>'9'||c<'0')&&c!='-') c=getchar(); if(c=='-') c=getchar(),q=1; while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } il void dfs(int u){BL[u]=u;sum[u]=v[u];sz[u]=1; for(RG int i=head[u];i!=-1;i=e[i].nxt){ RG int v=e[i].to; dfs(v);sum[u]+=sum[v]; sz[u]+=sz[v]; BL[u]=merge(BL[u],BL[v]); }while(sum[u]>m&&sz[u]){ sum[u]-=v[BL[u]]; BL[u]=merge(r[BL[u]],l[BL[u]]); sz[u]--; }ans=max(ans,(LL)sz[u]*L[u]); } int main(){ freopen("dispatching.in","r",stdin); freopen("dispatching.out","w",stdout); memset(head,-1,sizeof(head)); n=getint(),m=getint(); for(RG int i=1;i<=n;++i){int ytk; ytk=getint(),v[i]=getint(),L[i]=getint(); add(ytk,i); }dfs(1);printf("%lld",ans); return 0; }