【题目大意】

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 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=+;
  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=-;
  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==)?:;
  23. ltree[x].lson=ltree[x].rson=;
  24. ltree[x].dis=(x==)?-:;
  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=+ltree[l].size+ltree[r].size;
  32. }
  33.  
  34. int merge(int x,int y)
  35. {
  36. if (x==) return y;
  37. if (y==) 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==) ltree[x].dis=;
  44. else ltree[x].dis=ltree[r].dis+;
  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=;
  54. return merge(l,r);
  55. }
  56.  
  57. void init()
  58. {
  59. scanf("%d",&n);
  60. scanf("%lld",&m);
  61. for (int i=;i<=n;i++)
  62. {
  63. int b;
  64. long long c,l;
  65. scanf("%d%lld%lld",&b,&c,&l);
  66. if (b==) master=i;
  67. E[b].push_back(i);
  68. build(i,b,c,l);
  69. }
  70. build(,,,);
  71. }
  72.  
  73. int dfs(int u)
  74. {
  75. int rt=u;
  76. for (int i=;i<E[u].size();i++)
  77. {
  78. int to=E[u][i];
  79. rt=merge(rt,dfs(to));
  80. }
  81. while (ltree[rt].sum>m)
  82. {
  83. ltree[rt].sum-=ltree[rt].cost;
  84. ltree[rt].size--;
  85. rt=del(rt);
  86. }
  87. ans=max(ans,(ll)ltree[rt].size*(ll)ltree[u].key);
  88. return rt;
  89. }
  90.  
  91. void print_ans()
  92. {
  93. printf("%lld",ans);
  94. }
  95.  
  96. int main()
  97. {
  98. //freopen("dispatching.in","r",stdin);
  99. //freopen("dispatching.out","w",stdout);
  100. init();
  101. dfs(master);
  102. print_ans();
  103. return ;
  104. }

【左偏树】BZOJ2809-[APIO2012]dispatching的更多相关文章

  1. 【左偏树】[APIO2012]派遣

    题意可真的是有毒 第一眼树形背包可做?(反正我没用树形背包打过,边上巨佬打的背包似乎没拿分) 后来发现可以贪心搞,我们先把一个节点所有的儿子都取进去,之后不行的话再从大的开始拿走就好了 问题就变成了了 ...

  2. 【bzoj2809】[Apio2012]dispatching 左偏树

    2016-05-31  15:56:57 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 直观的思想是当领导力确定时,尽量选择薪水少的- ...

  3. bzoj2809 [Apio2012]dispatching(左偏树)

    [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 M ...

  4. 【BZOJ2809】【APIO2012】Dispatching(左偏树)

    题面 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个 ...

  5. [BZOJ2809][Apio2012]dispatching(左偏树)

    首先对于一个节点以及它的子树,它的最优方案显然是子树下选最小的几个 用左偏树维护出每棵子树最优方案的节点,记录答案 然后它的这棵树可以向上转移给父节点,将所有子节点的左偏树合并再维护就是父节点的最优方 ...

  6. 【BZOJ2809】[APIO2012] dispatching(左偏树例题)

    点此看题面 大致题意: 有\(N\)名忍者,每名忍者有三个属性:上司\(B_i\),薪水\(C_i\)和领导力\(L_i\).你要选择一个忍者作为管理者,然后在所有被他管理的忍者中选择若干名忍者,使薪 ...

  7. 【bzoj2809】[Apio2012]dispatching (左偏树)

    我们需要枚举根,然后从其子树内选尽量多的点,薪水不超过M,可是暴力复杂度不对.于是考虑自下而上合并树(开始每棵树内只有一个节点,就是自己) 每个树是一个堆,我们维护树的节点个数和薪水总和,合并时,不断 ...

  8. bzoj2809 [Apio2012]dispatching——左偏树(可并堆)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2809 思路有点暴力和贪心,就是 dfs 枚举每个点作为管理者: 当然它的子树中派遣出去的忍者 ...

  9. 【BZOJ 2809】2809: [Apio2012]dispatching (左偏树)

    2809: [Apio2012]dispatching Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Maste ...

随机推荐

  1. Django随笔 01

    Django 视图 不处理用户输入,而仅仅决定要展现哪些数据给用户: Django 模板 仅仅决定如何展现Django视图指定的数据. dd http://blog.csdn.net/pipisorr ...

  2. 团队代码中Bug太多怎么办?怎样稳步提高团队的代码质量

    最近负责的Android APP项目,由于团队成员变动.界面改版导致代码大幅修改等原因,产品发布后屡屡出现BUG导致的程序崩溃. 经过对异常统计和代码走读,BUG主要集中在空指针引起的NullPoin ...

  3. bootstrap table 怎么自适应宽度

    <div class="table-responsive"> <table class="table text-nowrap"> < ...

  4. 经典DFS问题 oilland 连通块

    #include "iostream" #include "cstdio" using namespace std; ][]={{,},{,-},{,},{-, ...

  5. 【STSRM13】木之本樱

    [题意]抽象模型后转化为:给定n个直线,ans+=C(x,4)*8,x为每个经过直线数>=4的点的直线数,不存在平行直线. [算法]数学 [题解] 运用了一个很简单的道理:经过同一个点的线段互相 ...

  6. How to learn wxPython

    目录 How to learn wxPython Learn Python Choose a good editor Install wxPython Read the wxPython tutori ...

  7. return 与 exit() 的区别

    return是一个关键字,返回函数值:exit()是一个函数: return是语言级的:exit()是操作系统提供的函数: return表示函数退出:exit()表示进程退出: 非主函数中调用retu ...

  8. springboot整合mybatis+pageHelper

    springboot整合mybatis+pageHelper 〇.搭建sporingboot环境,已经整合mybatis环境,本篇主要是添加pageHelper工具 一.添加依赖 <!-- 分页 ...

  9. go语言的定时器

    package main import ( "fmt" "time" ) func main(){ //创建一个定时器,时间为2s,2s过后会自动往通道里面写入 ...

  10. Selenium2+python自动化-窗口多标签处理方法总结(转载)

    本篇转自博客:上海-小T 原文地址:https://i.cnblogs.com/EditArticles.aspx?opt=1 我们在用Selenium遇到多个浏览器窗口或单个浏览器多个标签(Tab) ...