https://scut.online/p/131

首先假如钦定了一群人去打怪兽,那么可以把主要的任务都丢给b最大的人去打,这样不会更差。然后考虑枚举这个b最大的人,其他人陪练。一开始就是ai+k*bi+sumC-ci,这个很好理解,然后这个人分出至多t=k-1个怪兽给陪练团打,那么既然规定陪练团每个人只能选1只去打,那么肯定是贪心选vj=aj+bj-cj最大的t个人去打。搞个Treap(随便,但是WA了好多发)维护一下。

注意是我这个模板居然没有初始化,草,还要自己写。但是Treap具体的原理并不是很明白。

注意的WA点在于找不超过k个人,且v要大于bi的那堆和。当右子树为空并不代表可以退出,或者说,当现在进入第二个分类里面的时候,有可能这里的子树是有用的。

看见别人直接二分找,内心是一千个草泥马。唉就当学习一下平衡树。

注意空间要开双倍,因为insert有两次。除非弄个回收?回收很好办的,实测省略一点点空间。因为经过直觉最多同时存在n个点所以直接这样就可以了:搞个STLstack(不能用数组否则不是浪费自己表情?)newnode的时候从stack里面删除,remove的时候把id放回stack里面。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int MAXN = 200000;
  5. int ch[MAXN + 5][2];
  6. int val[MAXN + 5], dat[MAXN + 5];
  7. int siz[MAXN + 5], cnt[MAXN + 5];
  8. ll sum[MAXN + 5];
  9. int tot, root;
  10. inline void Init() {
  11. tot = 0;
  12. root = 0;
  13. }
  14. inline int NewNode(int v) {
  15. ch[++tot][0] = 0;
  16. ch[tot][1] = 0;
  17. val[tot] = v, dat[tot] = rand();
  18. siz[tot] = 1, cnt[tot] = 1;
  19. sum[tot] = v;
  20. return tot;
  21. }
  22. inline void PushUp(int id) {
  23. siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[id];
  24. sum[id] = sum[ch[id][0]] + sum[ch[id][1]] + 1ll * val[id] * cnt[id];
  25. }
  26. inline void Rotate(int &id, int d) {
  27. int temp = ch[id][d ^ 1];
  28. ch[id][d ^ 1] = ch[temp][d];
  29. ch[temp][d] = id;
  30. id = temp;
  31. PushUp(ch[id][d]), PushUp(id);
  32. }
  33. inline void Insert(int &id, int v) {
  34. if(!id)
  35. id = NewNode(v);
  36. else {
  37. if(v == val[id])
  38. ++cnt[id];
  39. else {
  40. int d = v < val[id] ? 0 : 1;
  41. Insert(ch[id][d], v);
  42. if(dat[id] < dat[ch[id][d]])
  43. Rotate(id, d ^ 1);
  44. }
  45. PushUp(id);
  46. }
  47. }
  48. void Remove(int &id, int v) {
  49. if(!id)
  50. return;
  51. else {
  52. if(v == val[id]) {
  53. if(cnt[id] > 1) {
  54. cnt[id]--;
  55. PushUp(id);
  56. } else if(ch[id][0] || ch[id][1]) {
  57. if(!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]])
  58. Rotate(id, 1), Remove(ch[id][1], v);
  59. else
  60. Rotate(id, 0), Remove(ch[id][0], v);
  61. PushUp(id);
  62. } else
  63. id = 0;
  64. } else {
  65. v < val[id] ? Remove(ch[id][0], v) : Remove(ch[id][1], v);
  66. PushUp(id);
  67. }
  68. }
  69. }
  70. ll GetSum(int bi, int k) {
  71. if(k == 0)
  72. return 0;
  73. //把大于bi的最大的至多k个v全部加起来,每加一个减去一个bi
  74. int r = root;
  75. ll res = 0;
  76. while(r) {
  77. if(bi >= val[r] || (ch[r][1] && siz[ch[r][1]] >= k)) {
  78. //bi不比这个节点小,这个节点没用,向右走
  79. //或者前k大完全在右子树中
  80. r = ch[r][1];
  81. continue;
  82. } else {
  83. //有用的完全在该节点及其右子树中
  84. /*if(!ch[r][1])
  85. return res;*/
  86. res += sum[ch[r][1]];
  87. res -= 1ll * siz[ch[r][1]] * bi;
  88. k -= siz[ch[r][1]];
  89. if(k <= cnt[r]) {
  90. res += 1ll * k * (val[r] - bi);
  91. k = 0;
  92. return res;
  93. }
  94. else{
  95. res += 1ll * cnt[r] * (val[r] - bi);
  96. k -=cnt[r];
  97. }
  98. r=ch[r][0];
  99. }
  100. }
  101. return res;
  102. }
  103. int n, k;
  104. struct Char {
  105. int a, b, c;
  106. int v;
  107. Char() {};
  108. Char(int _a, int _b, int _c) {
  109. a = _a;
  110. b = _b;
  111. c = _c;
  112. v = a + b - c;
  113. }
  114. } cha[100005];
  115. ll sumC;
  116. ll calc(int id) {
  117. ll M = sumC - cha[id].c + cha[id].a + 1ll * k * cha[id].b ;
  118. Remove(root, cha[id].v);
  119. //至多从平衡树拿走k-1个
  120. ll res = GetSum(cha[id].b, k - 1);
  121. Insert(root, cha[id].v);
  122. return M + res;
  123. }
  124. int main() {
  125. #ifdef Yinku
  126. freopen("Yinku.in", "r", stdin);
  127. #endif // Yinku
  128. int T;
  129. scanf("%d", &T);
  130. while(T--) {
  131. scanf("%d%d", &n, &k);
  132. sumC = 0;
  133. Init();
  134. for(int i = 1; i <= n; ++i) {
  135. int a, b, c;
  136. scanf("%d%d%d", &a, &b, &c);
  137. cha[i] = Char(a, b, c);
  138. sumC += c;
  139. Insert(root, cha[i].v);
  140. }
  141. ll ans = 0;
  142. for(int i = 1; i <= n; ++i)
  143. ans = max(ans, calc(i));
  144. printf("%lld\n", ans);
  145. }
  146. return 0;
  147. }

SCUT - 131 - 小P玩游戏II - 贪心 - 平衡树的更多相关文章

  1. JZOJ 5777. 【NOIP2008模拟】小x玩游戏

    5777. [NOIP2008模拟]小x玩游戏 (File IO): input:game.in output:game.out Time Limits: 1000 ms  Memory Limits ...

  2. 2783: 【基础】小 X 玩游戏(game)

    2783: [基础]小 X 玩游戏(game) 时间限制: 1 Sec 内存限制: 64 MB 提交: 752 解决: 294 [提交] [状态] [讨论版] [命题人:ghost79] 题目描述 听 ...

  3. P5676 [GZOI2017]小z玩游戏【Tarjan】

    小z玩游戏 Tarjan算是板子题吧,但是要稍微做一些修改,建边需要多考虑,建立"虚点". 题目描述 小 z 很无聊. 小 z 要玩游戏. 小 z 有\(N\)个新游戏,第\(i\ ...

  4. 力扣Leetcode 45. 跳跃游戏 II - 贪心思想

    这题是 55.跳跃游戏的升级版 力扣Leetcode 55. 跳跃游戏 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 你的目标是使用最少的跳跃 ...

  5. 【题解】 [GZOI2017]小z玩游戏

    题目戳我 \(\text{Solution:}\) 考虑建图.操作可以看作对\(1\)进行的操作,于是有以下运行过程: \(1\to w[i]\to e[i]\to...\) 考虑倍数,一个数可以走到 ...

  6. 神奇的建图方式(Tarjan)——小z玩游戏

    原题来自与:洛谷 P5676(GZOI2017)  链接: https://www.luogu.com.cn/problem/P5676 题面: 题意比较明显,如果已经建好了边,那么跑个Tarjan ...

  7. P5676 [GZOI2017]小z玩游戏 Tarjan+优化建图

    题目描述 分析 一开始看到这道题,首先想到的就是建好边后跑一个Tarjan缩点,将siz大于1的节点统计一下,输出结果 Tarjan非常显然易得,关键就是怎么建边 比较好想的一种思路就是枚举每一个兴奋 ...

  8. J - 玩游戏

    小A和小B玩游戏,初始的时候小A给小B一组包含n个数的数组.他们按如下的规则进行: 每次小B得到一组数,他把这组数的和加到自己的分数里面(他的初始分数是0),然后他把这组数还给小A. 如果小A得到的这 ...

  9. HihoCoder - 1615矩阵游戏II(贪心)

    矩阵游戏II 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个NxN的整数矩阵,小Hi每次操作可以选择两列,将这两列中的所有数变成它的相反数. 小Hi可以进行任意 ...

随机推荐

  1. Vuejs使用scoped(私有) style为v-html中标签添加CSS样式

    最近使用Vue框架的时候遇到一个问题,就是后台把数据写好了,而且写好的数据的某些内容是html格式的,使用Vue框架的v-html虽然可以很简单的就把数据转换成html的标签渲染在页面上,但是有些样式 ...

  2. Python图谱

    Reference: https://time.geekbang.org/column/article/94311

  3. 不同地区Android开发者使用哪些设备测试APP?

    我们的团队密切关注着移动世界的趋势,以便可以提供所有有关变化的最紧密和最重要的信息.春天恰好是对app进行新一轮测试并检查其与不同Android设备兼容性如何的最佳时机.下面让我们一起来看看全世界范围 ...

  4. [CSP-S模拟测试]:炼金术士的疑惑(模拟+数学+高斯消元)

    题目传送门(内部题70) 输入格式 第一行一个正整数$n$,表示炼金术士已知的热化学方程式数量.接下来$n$行,每行一个炼金术士已知的热化学方程式.最后一行一个炼金术士想要求解的热化学方程式,末尾记为 ...

  5. 大数据笔记(一)——Hadoop的起源与背景知识

    一.大数据的5个特征(IBM提出): Volume(大量) Velocity(高速) Variety(多样) Value(价值) Varacity(真实性) 二.OLTP与OLAP 1.OLTP:联机 ...

  6. (转)Matplotlib的子图subplot的使用

    转:https://www.jianshu.com/p/de223a79217a 前言 Matplotlib的可以把很多张图画到一个显示界面,这就设计到面板切分成一个一个子图.这是怎么做到的呢.mat ...

  7. Matlab 中 函数circshift()的用法

    a = [ ; ; ]; b = [- - -; - - -;- - -]; c = [ ; ; ]; Hist(:,:,) = a; Hist(:,:,) = b; Hist(:,:,) = c; ...

  8. Oracle Flashback Transaction Query with Oracle Flashback Version Query

    Oracle Flashback Transaction Query with Oracle Flashback Version Query In this example, a database a ...

  9. sh/bash/csh/Tcsh/ksh/pdksh等shell的区别

    w shell confusion..what is diff between bash, ksh, csh, tcsh..??  http://www.linuxquestions.org/ques ...

  10. JS-Array.prototype 中的方法的坑

    fill() 今天刷 HackerRank 的题遇到需要创建链表数组(一维数组的每一项是个链表)的题. 众所周知 JS 中的数组可以当链表用,我就用如下代码进行创建 let seqs = (new A ...