在這個幫派裡,有一名忍者被稱之為master。除了master以外,每名忍者都有且僅有乙個上級。為保密,同時增強忍者們的領導力,所有與他們工作相關的指令總是由上級傳送給他的直接下屬,而不允許通過其他的方式傳送。
現在你要招募一批忍者,並把它們派遣給顧客。你需要為每個被派遣的忍者支付一定的薪水,同時使得支付的薪水總額不超過你的預算。另外,為了傳送指令,你需要選擇一名忍者作為管理者,要求這個管理者可以向所有被派遣的忍者傳送指令,在傳送指令時,任何忍者(不管是否被派遣)都可以作為訊息的傳遞人。管理者自己可以被派遣,也可以不被派遣。當然,如果管理者沒有被排遣,你就不需要支付管理者的薪水。
你的目標是在預算內使顧客的滿意度最大。這裡定義顧客的滿意度為派遣的忍者總數乘以管理者的領導力水平,其中每個忍者的領導力水平也是一定的。
寫乙個程式,給定每乙個忍者i的上級bi,薪水ci,領導力li,以及支付給忍者們的薪水總預算m,輸出在預算內滿足上述要求時顧客滿意度的最大值。
1 ≤ n ≤ 100,000 忍者的個數;
1 ≤ m ≤ 1,000,000,000 薪水總預算;
0 ≤ bi < i 忍者的上級的編號;
1 ≤ ci ≤ m 忍者的薪水;
1 ≤ li ≤ 1,000,000,000 忍者的領導力水平。
可以想到貪心的思路,對於每個節點,找他及其子樹薪水最小的一些,加起來不超過m;
這時就可以運用到可並堆了,左偏樹是其中一種實現方式。
我還不怎麼會,可以看看這個
#includeusingview codenamespace
std;
//左偏樹
#define ll long long
const
int maxn=100005
;int
n;ll m,ans;
int root[maxn],ls[maxn],rs[maxn],dis[maxn];//
root:i及其子樹形成的大根堆的根 dis:i到外節點的距離
ll sum[maxn],size[maxn];//
i及其子樹形成的根的薪水和、人數
struct
persona[maxn];
template
inline void read(t &x)
}void build(int
x) int merge(int a,int
b)int
main();
build(i);
//自身成為乙個堆
ans=max(ans,z);
}for(int i=n;i;i--)
ans=max(ans,a[f].power*size[f]);
}printf(
"%lld
",ans);
}
還可以用可合併值域線段樹,現在還不會,之後再寫。
APIO2012 派遣 題解
這題還是非常顯然的 題意大概是隨便選乙個點x,樹上每點有點權 v x 和乙個代價 c x 你有乙個值m,設,我們用m可以最多大於y x 個x的子樹中代價的和,求出所有點的y x v x 的值,其中最大值就是答案。非常顯然用線段樹合併 還有可並堆的做法,不怎麼會會,下次學 include includ...
APIO2012 派遣 解題報告
問題描述 在乙個忍者的幫派裡,一些忍者們被選中派遣給顧客,然後依據自己的工作獲取報償。在這個幫派裡,有一名忍者被稱之為master。除了master以外,每名忍者都有且僅有乙個上級。為保密,同時增強忍者們的領導力,所有與他們工作相關的指令總是由上級傳送給他的直接下屬,而不允許通過其他的方式傳送。現在...
APIO2012 派遣 左偏樹
題面 考慮列舉每個節點作為管理者,計算所獲得的滿意程度以更新答案。對於每個節點的計算,貪心,維護乙個大根堆,每次彈出薪水最大的人。這裡注意,一旦乙個人被彈出,那麼不再可能出現在其祖先們的最優解裡 廢話 所以使用可並堆左偏樹優化複雜度。include include define maxn 10001...