题目大意:给出一棵树,每个节点有两个值,各自是这个忍者的薪水和忍者的领导力。客户的惬意程度是这个点的领导力乘可以取得人数。前提是取的人的薪水总和不超过总的钱数。

思路:仅仅能在子树中操作。贪心的想,我们仅仅要这个子树中cost最小的那些点就能够了。

所以就深搜一次。每到一个节点上。把自己和全部子节点的平衡树启示式和并,然后保留不超过总钱数的人数。统计。数据范围比較大,能开long long的地方不要吝啬。

PS:吐槽一下,一開始这个题一直TTT。我以为是我常数写的太大了。别人都用左偏堆写。是不是平衡树已经成为了时代的眼泪了。

。。

后来我搞到了測点。跑了一下第一组数据等了1分多钟都没出解。

我感觉我又要重写了。就出去转转。十分钟之后我回来发现竟然出解了。并且竟然还对了!!

然后我细致看了一遍程序。

。发现是启示式合并写反了。。。。写反了。。。反了。。。

了。。。

CODE:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #define MAX 100010
  6. using namespace std;
  7.  
  8. struct Complex{
  9. long long cost,leader;
  10. }point[MAX];
  11.  
  12. struct Treap{
  13. int random,size,cnt;
  14. long long val,sum;
  15. Treap *son[2];
  16.  
  17. Treap(long long _) {
  18. val = sum = _;
  19. size = cnt = 1;
  20. random = rand();
  21. son[0] = son[1] = NULL;
  22. }
  23. int Compare(long long x) {
  24. if(x == val) return -1;
  25. return x > val;
  26. }
  27. void Maintain() {
  28. size = cnt;
  29. sum = val * cnt;
  30. if(son[0] != NULL) size += son[0]->size,sum += son[0]->sum;
  31. if(son[1] != NULL) size += son[1]->size,sum += son[1]->sum;
  32. }
  33. }*tree[MAX];
  34.  
  35. long long points,money;
  36. int head[MAX],total;
  37. int next[MAX << 1],aim[MAX << 1];
  38.  
  39. long long ans;
  40.  
  41. inline void Add(int x,int y)
  42. {
  43. next[++total] = head[x];
  44. aim[total] = y;
  45. head[x] = total;
  46. }
  47.  
  48. inline void Rotate(Treap *&a,bool dir)
  49. {
  50. Treap *k = a->son[!dir];
  51. a->son[!dir] = k->son[dir];
  52. k->son[dir] = a;
  53. a->Maintain(),k->Maintain();
  54. a = k;
  55. }
  56.  
  57. inline void Insert(Treap *&a,long long x)
  58. {
  59. if(a == NULL) {
  60. a = new Treap(x);
  61. return ;
  62. }
  63. int dir = a->Compare(x);
  64. if(dir == -1) ++a->cnt;
  65. else {
  66. Insert(a->son[dir],x);
  67. if(a->son[dir]->random > a->random)
  68. Rotate(a,!dir);
  69. }
  70. a->Maintain();
  71. }
  72.  
  73. inline int FindMax(Treap *a)
  74. {
  75. return a->son[1] == NULL ?
  76.  
  77. a->val:FindMax(a->son[1]);
  78. }
  79.  
  80. inline void Delete(Treap *&a,long long x)
  81. {
  82. int dir = a->Compare(x);
  83. if(dir != -1) Delete(a->son[dir],x);
  84. else {
  85. if(a->cnt > 1) --a->cnt;
  86. else {
  87. if(a->son[0] == NULL) a = a->son[1];
  88. else if(a->son[1] == NULL) a = a->son[0];
  89. else {
  90. bool _ = (a->son[0]->random > a->son[1]->random);
  91. Rotate(a,_);
  92. Delete(a->son[_],x);
  93. }
  94. }
  95. }
  96. if(a != NULL) a->Maintain();
  97. }
  98.  
  99. void Transfrom(Treap *&from,Treap *&aim)
  100. {
  101. if(from == NULL) return ;
  102. Transfrom(from->son[0],aim);
  103. Transfrom(from->son[1],aim);
  104. for(int i = 1; i <= from->cnt; ++i)
  105. Insert(aim,from->val);
  106. delete from;
  107. from = NULL;
  108. }
  109.  
  110. void DFS(int x)
  111. {
  112. tree[x] = new Treap(point[x].cost);
  113. if(point[x].cost <= money)
  114. ans = max(ans,(long long)point[x].leader);
  115. if(!head[x])
  116. return ;
  117. for(int i = head[x]; i; i = next[i]) {
  118. DFS(aim[i]);
  119. if(tree[x]->size < tree[aim[i]]->size)
  120. swap(tree[x],tree[aim[i]]);
  121. Transfrom(tree[aim[i]],tree[x]);
  122. }
  123. while(tree[x]->sum > money)
  124. Delete(tree[x],FindMax(tree[x]));
  125. ans = max(ans,(long long)tree[x]->size * point[x].leader);
  126. }
  127.  
  128. int main()
  129. {
  130. cin >> points >> money;
  131. for(int x,i = 1; i <= points; ++i) {
  132. scanf("%d%lld%lld",&x,&point[i].cost,&point[i].leader);
  133. Add(x,i);
  134. }
  135. DFS(0);
  136. cout << ans << endl;
  137. return 0;
  138. }

BZOJ 2809 APIO 2012 dispatching 平衡树启示式合并的更多相关文章

  1. BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆

    题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定 ...

  2. BZOJ 2733 HNOI 2012 永无乡 平衡树启示式合并

    题目大意:有一些岛屿,一開始由一些无向边连接. 后来也有不断的无向边增加,每个岛屿有个一独一无二的重要度,问随意时刻的与一个岛屿联通的全部岛中重要度第k大的岛的编号是什么. 思路:首先连通性一定要用并 ...

  3. bzoj 2809 左偏树\平衡树启发式合并

    首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...

  4. 【BZOJ 2809】 [Apio2012]dispatching

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

  5. APIO 2012 派遣(可并堆)

    APIO 2012 派遣(可并堆) 给定一棵N个点的树和M,每个点有两个权值ai,bi,每次可以选择一个点x,然后在这个点的子树中选若干点(可以不选自己),使得这些点的\(\sum b_i<=M ...

  6. 【BZOJ 2809】【APIO 2012】dispatching

    昨天晚上zyf神犇问我的题,虽然我太弱参加不了APIO但也做一做吧. 用小数据拍了无数次总是查不出错来,交上去就WA,后来用国内数据测发现是主席树上区间相减的值没有用long long存,小数据真是没 ...

  7. 「BZOJ 2809」「APIO 2012」Dispatching「启发式合并」

    题意 给定一个\(1\)为根的树,每个点有\(c,w\)两个属性,你需要从某个点\(u\)子树里选择\(k\)个点,满足选出来的点\(\sum_{i=1}^k w(i)\leq m\),最大化\(k\ ...

  8. BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )

    枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...

  9. bzoj 2809: [Apio2012]dispatching -- 可并堆

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...

随机推荐

  1. PHP方法之 substr

    简单描述: substr 主要用于字符串的截取,但是不适用于中文字符串,易出现乱码,中文字符串可使用mbstring. 方法申明: substr(string,start,length) string ...

  2. boot_mem分配器

    #define alloc_bootmem_low_pages(x) \ __alloc_bootmem_low(x, PAGE_SIZE, ) void * __init __alloc_bootm ...

  3. Linux中断底半部机制

    参考: Linux下半部处理之软中断 linux中断底半部机制 <深入理解Linux内核>软中断/tasklet/工作队列 软中断和tasklet介绍 详解操作系统中断 Linux内核:中 ...

  4. uboot的Makefile裁剪(针对飞思卡尔的mx6系列)

    VERSION = 2009PATCHLEVEL = 08SUBLEVEL =EXTRAVERSION =ifneq "$(SUBLEVEL)" ""U_BOO ...

  5. 九度oj 题目1139:最大子矩阵

    题目描述: 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 ...

  6. linux删除N天前的文件

    列出一天之前的文件的属性用下面的命令:find . ! -mtime -1 -print |xargs ls -lfind . -mtime +1 要删除文件的话用下面的命令:find . ! -mt ...

  7. BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组

    我们只需要统计在某一个点开始的形如$AA$字符串个数,和结束的个数相乘求和. 首先枚举循环节的长度L.即$\mid (A) \mid=L$ 然后肯定会经过s[i]和[i+L]至少两个点. 然后我们可以 ...

  8. 2013 年 acm 长春现场赛

    A - Hard Code Hdu 4813 题目大意:给你一坨字符串,让你输出其栅栏密码的解码形式 思路:水题模拟 #include<iostream> #include<cstd ...

  9. mybatis学习(三)——接口式编程

    对于上一节中的查询我们还可以通过接口的方式进行编程,开发环境和上一节一样 1.全局配置文件mybatis_config.xml(和上一节一样) <?xml version="1.0&q ...

  10. weixin-api生成二维码

    二维码长链接转成短链接(减少扫描时间和提高成功率) 微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了 ...