[BZOJ2809] [Apio2012]dispatching

来源:互联网 发布:苹果编程 编辑:程序博客网 时间:2024/06/15 19:50

题意

N个点形成一棵树。每个点三个属性父亲节点Bi、薪水Ci、领导力Li,现在选一些点,对这些点付薪水,同时另选一个点(可以是之前被付薪水的点)做管理者,使得被付薪水的点都在管理者的子树中。定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,在预算M内使顾客的满意度最大。输出最大的满意度。

题解

相同的预算,薪水尽量少则选的点尽量多,于是每个子树中维护一个大根堆,不断删掉堆顶直到堆中元素的和不超过M,统计完当前子树后向上合并堆。
1:启发式合并优先队列 1564 ms
2:左偏树合并 984 ms
下面是左偏树代码

代码

/// by ztx/// blog.csdn.net/hzoi_ztx#include <bits/stdc++.h>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)#define Each(i,v)  for(i=v.begin();i!=v.end();i++)typedef long long ll ;typedef double lf ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}#define  kN  100010LLstruct lt {    lt *l, *r;    int sz, w, d;    lt();    lt(int w);}*null=new lt();lt::lt() { l=r=null;w=d=sz=0; }lt::lt(int w): w(w) { l=r=null;d=0;sz=1; }lt* Init(int x) { return new lt(x); }lt* Merge(lt*u,lt*v) {    if (u == null) return v;    if (v == null) return u;    if (u->w < v->w) std::swap(u,v);    u->r = Merge(u->r,v);    if (u->l->d < u->r->d) std::swap(u->l,u->r);    u->d = u->r->d+1;    u->sz = u->l->sz+u->r->sz+1;    return u;}void Insert(lt*&u,int x) { u = Merge(u,Init(x)); }int Top(lt*u) { return u->w; }void Pop(lt*&u) { lt*tmp = u; u = Merge(u->l,u->r); delete tmp; }bool Empty(lt*u) { return u == null; }int Size(lt*u) { return u->sz; }int n, lim;int fa[kN], cost[kN], lead[kN];lt* q[kN];ll sum[kN];#define r(x)   read(x)int main() {    int i;    ll tmp, ans = 0;    r(n), r(lim);    Rep (i,1,n)        r(fa[i]), r(cost[i]), r(lead[i]),        q[i] = Init(cost[i]), sum[i] = cost[i];    Rev (i,n,1) {        while (sum[i] > lim)            sum[i] -= Top(q[i]), Pop(q[i]);        if (tmp=1LL*lead[i]*Size(q[i]), tmp>ans) ans = tmp;        if (fa[i] > 0) {            sum[fa[i]] += sum[i];            q[fa[i]] = Merge(q[i],q[fa[i]]);        }    }    printf("%lld\n", ans);    END: getchar(), getchar();    return 0;}
原创粉丝点击