Dispatching左偏树

来源:互联网 发布:java线程yield 编辑:程序博客网 时间:2024/06/05 04:20

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。

输入格式:
从标准输入读入数据。

第一行包含两个整数 N和 M,其中 N表示忍者的个数,M表示薪水的总预算。

接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整 Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力。Master满足B i = 0,并且每一个忍者的老板的编号一定小于自己的编号 Bi < i。
输出格式:
输出一个数,表示在预算内顾客的满意度的最大值。
样例输入:
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
样例输出:
6
数据范围:
1 ≤N ≤ 100,000 忍者的个数;
1 ≤M ≤ 1,000,000,000 薪水总预算;

0 ≤Bi < i 忍者的上级的编号;
1 ≤Ci ≤ M 忍者的薪水;
1 ≤Li ≤ 1,000,000,000 忍者的领导力水平。
时间限制:
1s
空间限制:
128MB

左偏树支持nlogn的均摊时间合并,用它显然快且稳定,可以支持上传操作,我们这道题显然就是一个对于一个点在他的子树中在一定代价内取最多的儿子的问题,可以先来一遍深搜,从下往上合并,把最大的不用的那几个删去就可以AC了,si表示选的儿子的数量
另:左偏树的基本操作均由merge完成,我们维护他的堆性质,并且对于他的distance(该节点离他最近的儿子少于2个的点到他的距离)我们要维护,他的左子树的dis大于等于右子树的dis,不满足就交换,然后递归维护他的右儿子与另一个树的并,他作为该子树的根返回,如果一个子树为空就直接返回另一个
合并即merge
insert:把该数当作一棵树扔入
delete:合并其左右子树

%:pragma GCC optimize(3)#include<bits/stdc++.h>//#include<windows.h>using namespace std;#define PER(i,a,b) for(int i=a;i<=b;i++)#define forw(i,x) for(int i=fir[x];i;i=ne[i])#define N 200001long long L[N],R[N],n,m,ch[N][2];long long ne[N],fir[N],to[N],val[N],nu[N],l[N],cnt,sum[N],d[N],root[N],si[N];long long ans=0;void add(int x,int y){    to[++cnt]=y;ne[cnt]=fir[x];fir[x]=cnt;}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(d[ch[x][0]]<d[ch[x][1]]) swap(ch[x][1],ch[x][0]);    d[x]=d[ch[x][1]]+1;    return x;}void dfs(int x){//  cout<<x<<endl;Sleep(500);    root[x]=x;sum[x]=val[x];si[x]=1;    forw(i,x)    {        int v=to[i];dfs(v);        sum[x]+=sum[v];si[x]+=si[v];root[x]=merge(root[x],root[v]);    }    while(sum[x]>m)    {        sum[x]-=val[root[x]];        si[x]--;        root[x]=merge(ch[root[x]][1],ch[root[x]][0]);    }    ans=max(ans,(long long) l[x]*si[x]);}int main(){    cin>>n>>m;    for(int i=1;i<=n;i++)    {        long long x;        cin>>x>>val[i]>>l[i];        add(x,i);    }    d[0]=-1;    dfs(1);    cout<<ans<<endl;}