[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

Sample Output

6
 

HINT

 



如果我們選擇編號爲 1的忍者作爲管理者並且派遣第三個和第四個忍者,薪水總和爲 4,沒有超過總預算                         4。因爲派遣了                              2   個忍者並且管理者的領導力爲      3,

用戶的滿意度爲 2      ,是可以得到的用戶滿意度的最大值。

 

Source

 

思維難度:省選

代碼難度:NOIP+

算法:左偏樹

 

#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
const int Maxn=200005;
ll n,m,val[Maxn],cnt,h[Maxn],cost[Maxn],sum[Maxn],ch[Maxn][2],ans,dis[Maxn],sz[Maxn],rt[Maxn];
struct node{
    ll v,next;
}e[Maxn*2];
void add(ll u,ll v){
    cnt++;
    e[cnt].v=v;
    e[cnt].next=h[u];
    h[u]=cnt;
}
inline ll read(){
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar(); 
    }
    while(c<='9'&&c>='0'){
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
inline ll mx(ll x,ll y){
    return x>y?x:y;
}
inline void pushup(ll x){
    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+cost[x];
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
inline ll merge(ll x,ll y){
    if(!x||!y)return x+y;
    if(cost[x]<cost[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;
    pushup(x);
    return x;
} 
inline ll delet(ll x){
    return merge(ch[x][0],ch[x][1]);
}
void dfs(ll u){
    sum[u]=cost[u];sz[u]=1;rt[u]=u;
    for(ll i=h[u];i;i=e[i].next){
        ll v=e[i].v;
        dfs(v);
        rt[u]=merge(rt[u],rt[v]);
        while(sum[rt[u]]>m){
            rt[u]=delet(rt[u]);
        }
        ans=mx(ans,sz[rt[u]]*val[u]);
    }
}
int main(){
    ll u;
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++){
        u=read();cost[i]=read();val[i]=read();
        add(u,i);
        ans=mx(val[i],ans);
    }
    dfs(1);
    printf("%lld\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章