【左偏树】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 }