【左偏树】BZOJ2809-[APIO2012]dispatching

【题目大意】

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

【思路】

通过dfs,从下往上,每次合并堆,如果总的薪水大于预期值,就弹出堆顶(即薪水最高的那个),直到小于预期值即可,每次dfs都更新一下答案。

【错误点】

写在程序里面了!比较的关键字是cost不是sum!!!!!!!!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 using namespace std;
  7 typedef long long ll;
  8 const int MAXN=100000+500;
  9 struct node
 10 {
 11     ll cost,key,sum;
 12     int size,dis,lson,rson;
 13 }ltree[MAXN];
 14 int n,master;
 15 ll m,ans=-1;
 16 vector<int> E[MAXN];
 17 
 18 void build(int x,int fa,ll salary,ll leading)
 19 {
 20     ltree[x].cost=ltree[x].sum=salary;
 21     ltree[x].key=leading;
 22     ltree[x].size=(x==0)?0:1;
 23     ltree[x].lson=ltree[x].rson=0;
 24     ltree[x].dis=(x==0)?-1:0;
 25 }
 26 
 27 void pushup(int x)
 28 {
 29     int l=ltree[x].lson,r=ltree[x].rson;
 30     ltree[x].sum=ltree[x].cost+ltree[l].sum+ltree[r].sum;
 31     ltree[x].size=1+ltree[l].size+ltree[r].size;
 32 } 
 33 
 34 int merge(int x,int y)
 35 {
 36     if (x==0) return y;
 37     if (y==0) return x;
 38     if (ltree[x].cost<ltree[y].cost) swap(x,y);
 39     /*这里比较大小是cost之间,而不是sum之间……检查了一个下午才发现!!!!!!*/ 
 40     ltree[x].rson=merge(ltree[x].rson,y);
 41     int &l=ltree[x].lson,&r=ltree[x].rson;
 42     if (ltree[l].dis<ltree[r].dis) swap(l,r);
 43     if (r==0) ltree[x].dis=0;
 44         else ltree[x].dis=ltree[r].dis+1;
 45     pushup(x);
 46     return x;
 47 }
 48 
 49 int del(int rt)
 50 {
 51     int l=ltree[rt].lson;
 52     int r=ltree[rt].rson;
 53     ltree[rt].dis=ltree[rt].lson=ltree[rt].rson=0;
 54     return merge(l,r);
 55 }
 56 
 57 
 58 void init()
 59 {
 60     scanf("%d",&n);
 61     scanf("%lld",&m);
 62     for (int i=1;i<=n;i++)
 63     {
 64         int b;
 65         long long c,l;
 66         scanf("%d%lld%lld",&b,&c,&l);
 67         if (b==0) master=i;
 68         E[b].push_back(i);
 69         build(i,b,c,l);
 70     }
 71     build(0,0,0,0);
 72 }
 73 
 74 int dfs(int u)
 75 {
 76     int rt=u;
 77     for (int i=0;i<E[u].size();i++)
 78     {
 79         int to=E[u][i];
 80         rt=merge(rt,dfs(to));
 81     }
 82     while (ltree[rt].sum>m)
 83     {
 84         ltree[rt].sum-=ltree[rt].cost;
 85         ltree[rt].size--;
 86         rt=del(rt);
 87     }
 88     ans=max(ans,(ll)ltree[rt].size*(ll)ltree[u].key);
 89     return rt;
 90 }
 91 
 92 void print_ans()
 93 {
 94     printf("%lld",ans);
 95 } 
 96 
 97 int main()
 98 {
 99     //freopen("dispatching.in","r",stdin);
100     //freopen("dispatching.out","w",stdout);
101     init();
102     dfs(master);
103     print_ans(); 
104     return 0;
105 }
原文地址:https://www.cnblogs.com/iiyiyi/p/5656143.html