题目描述

        “伟大的勇士兔栽栗女王,所有栗子看到您都不寒而栗,但也非常尊重您。您骑着威风凛凛的小白兔,带领兔栽栗们奋勇前行。伟大史诗告诉我们,烈兔勇栗从大草原飞奔出来,冲在每场战争的前线——无论您在哪里,他们都能找到您。骑小白兔飞驰吧,凶猛的女王,但愿您有真正的朋友和软弱的敌人。”
        今天,冰雪聪明的栗酱终于玩到了她梦寐很久的文明游戏。
        不过作为一个萌新,兔头獐脑的栗酱自然不愿意第一次玩就遇到一个尴尬的开局,于是希望通过你来寻找一个完美开局。

已知开始时场上有n个国家,每个国家有一个初始人口基数ai,2个人口基数均不为0的国家间可以进行一场战争,而战争会使这两个国家的人口基数分别下降1,任意2个国家之间最多进行一场战争。
        完美开局的定义是:存在一种战争集合,当这些战争完成以后,所有国家的人口基数总和取得最小值。
        现在请你输出完美开局下所有国家的人口基数之和。

输入描述:

第一行一个数T,表示有T组数据。
对于每组数据,第一行输入一个数n,表示国家的数量,接下来一行输入n个数,
a1,a2,…,an, 其中ai表示第i个国家的初始人口基数。
每两个相邻的数之间用空格隔开。

输出描述:

  1. 对于每一个询问,输出一个数,即完美开局下所有国家的人口基数之和。
示例1

输入

  1. 2
  2. 4
  3. 3 3 3 3
  4. 8
  5. 3 4 3 4 1 3 3 4

输出

  1. 0
  2. 1

说明

  1. 对于第一个样例:
    国家1与国家2之间进行一场战争,剩下的人口基数为:2 2 3 3
    国家1与国家3之间进行一场战争,剩下的人口基数为:1 2 2 3
    国家1与国家4之间进行一场战争,剩下的人口基数为:0 2 2 2
    国家2与国家3之间进行一场战争,剩下的人口基数为:0 1 1 2
    国家2与国家4之间进行一场战争,剩下的人口基数为:0 0 1 1
    国家3与国家4之间进行一场战争,剩下的人口基数为:0 0 0 0
    任意两个国家之间恰好分别发生一场战争,剩余人口基数和取得最小值0

备注:

T≤10
1≤n≤105
1≤ai≤n

题解

线段树,贪心,Havel-Hakimi定理。

操作步骤和Havel-Hakimi定理相同,只是要拿线段树优化一下操作。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = 100000 + 10;
  5. int T, n;
  6. int a[maxn];
  7. int s[maxn * 4];
  8. int f[maxn * 4];
  9.  
  10. void pushDown(int rt) {
  11. if(f[rt] == 0) return;
  12. s[2 * rt] = s[2 * rt] - f[rt];
  13. s[2 * rt + 1] = s[2 * rt + 1] - f[rt];
  14. f[2 * rt] = f[2 * rt] + f[rt];
  15. f[2 * rt + 1] = f[2 * rt + 1] + f[rt];
  16. f[rt] = 0;
  17. }
  18.  
  19. void pushUp(int rt) {
  20. s[rt] = max(s[2 * rt], s[2 * rt + 1]);
  21. }
  22.  
  23. void build(int l, int r, int rt) {
  24. f[rt] = 0;
  25. if(l == r) {
  26. s[rt] = a[l];
  27. return;
  28. }
  29. int mid = (l + r) / 2;
  30. build(l, mid, 2 * rt);
  31. build(mid + 1, r, 2 * rt + 1);
  32. pushUp(rt);
  33. }
  34.  
  35. int get(int p, int l, int r, int rt) {
  36. if(l == r) {
  37. return s[rt];
  38. }
  39. int res;
  40. int mid = (l + r) / 2;
  41. pushDown(rt);
  42. if(p <= mid) res = get(p, l, mid, 2 * rt);
  43. else res = get(p, mid + 1, r, 2 * rt + 1);
  44. pushUp(rt);
  45. return res;
  46. }
  47.  
  48. void update(int L, int R, int val, int l, int r, int rt) {
  49. if(L <= l && r <= R) {
  50. f[rt] = f[rt] + val;
  51. s[rt] = s[rt] - val;
  52. return;
  53. }
  54. int mid = (l + r) / 2;
  55. pushDown(rt);
  56. if(L <= mid) update(L, R, val, l, mid, 2 * rt);
  57. if(R > mid) update(L, R, val, mid + 1, r, 2 * rt + 1);
  58. pushUp(rt);
  59. }
  60.  
  61. int first(int l, int r, int rt) {
  62. if(l == r) {
  63. return l;
  64. }
  65. int mid = (l + r) / 2;
  66. int res;
  67. pushDown(rt);
  68. if(s[2 * rt] > 0) res = first(l, mid, 2 * rt);
  69. else res = first(mid + 1, r, 2 * rt + 1);
  70. pushUp(rt);
  71. return res;
  72. }
  73.  
  74. int main() {
  75. scanf("%d", &T);
  76. while(T --) {
  77. scanf("%d", &n);
  78. for(int i = 1; i <= n; i ++) {
  79. scanf("%d", &a[i]);
  80. }
  81. sort(a + 1, a + 1 + n);
  82. build(1, n, 1);
  83. for(int i = n; i >= 1; i --) {
  84. int y = first(1, n, 1);
  85. if(y >= i) break;
  86. int x = get(i, 1, n, 1);
  87. if(x >= i - y) {
  88. update(i, i, i - y, 1, n, 1);
  89. update(y, i - 1, 1, 1, n, 1);
  90. } else {
  91. update(i, i, x, 1, n, 1);
  92. update(i - x, i - 1, 1, 1, n, 1);
  93. if(get(i - x - 1, 1, n, 1) > get(i - x, 1, n, 1)) {
  94. int L1, R1 = i - x - 1;
  95. int L2 = i - x, R2;
  96. int left, right;
  97. left = y, right = i - x - 1;
  98. while(left <= right) {
  99. int mid = (left + right) / 2;
  100. if(get(mid, 1, n, 1) < get(i - x - 1, 1, n, 1)) {
  101. left = mid + 1;
  102. } else {
  103. right = mid - 1;
  104. L1 = mid;
  105. }
  106. }
  107. left = i - x, right = i - 1;
  108. while(left <= right) {
  109. int mid = (left + right) / 2;
  110. if(get(mid, 1, n, 1) > get(i - x, 1, n, 1)) {
  111. right = mid - 1;
  112. } else {
  113. left = mid + 1;
  114. R2 = mid;
  115. }
  116. }
  117. //[L1, R1] [L2, R2];
  118. if(R1 - L1 == R2 - L2) {
  119. update(L1, R1, 1, 1, n, 1);
  120. update(L2, R2, -1, 1, n, 1);
  121. } else if(R1 - L1 > R2 - L2) {
  122. update(L2, R2, -1, 1, n, 1);
  123. update(L1, L1 + R2 - L2, 1, 1, n, 1);
  124. } else {
  125. update(L1, R1, 1, 1, n, 1);
  126. update(R2 + L1 - R1, R2, -1, 1, n, 1);
  127. }
  128. }
  129. }
  130. }
  131. long long ans = 0;
  132. for(int i = 1; i <= n; i ++) {
  133. ans = ans + (long long)get(i, 1, n, 1);
  134. }
  135. printf("%lld\n", ans);
  136. }
  137. return 0;
  138. }

  

2017年浙江工业大学大学生程序设计迎新赛预赛 H - 栗酱的文明的更多相关文章

  1. 2017年浙江工业大学大学生程序设计迎新赛热身赛-J-Forever97与寄信

    Forever97与未央是一对笔友,他们经常互相写信.有一天Forever97去邮局寄信,发现邮局的收费方式变成了按字收费,收取的费用为总字数除了其自身以外的最大因子.虽然Forever97是一个有情 ...

  2. 2017年浙江工业大学之江学院程序设计竞赛决赛 I: qwb VS 去污棒(可持久化Trie+离线)

    问题 I: qwb VS 去污棒 时间限制: 2 Sec  内存限制: 256 MB 提交: 74  解决: 26 [提交][状态][讨论版] 题目描述 qwb表白学姐失败后,郁郁寡欢,整天坐在太阳底 ...

  3. 2017年浙江中医药大学大学生程序设计竞赛(重现赛)D - CC的神奇背包

    题目描述 cc最近收到了好多礼物,对着满地大小不一的礼物,她想要一个包来装,于是dd就掏出了一个会说话的神奇背包给cc装礼物.cc为了一次性装尽可能多的礼物,于是跟这个背包定下了一个规则,对每个礼物, ...

  4. 中国(北方)大学生程序设计训练赛(第二周) (A B D G)

    比赛链接 A题是KMP,先把A拼接到B的后面,然后利用next数组的意义(包括其具体含义,以及失配时的应用),得到ans #include<bits/stdc++.h> using nam ...

  5. 中国(北方)大学生程序设计训练赛(第一周) (D E)

    比赛链接 D题是个二分,每次check复杂度为O(n),类似于xdu_1068,只是一个是求积,一个是求商 #include<bits/stdc++.h> using namespace ...

  6. 2017中国大学生程序设计竞赛-哈尔滨站 H - A Simple Stone Game

    A Simple Stone Game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Ot ...

  7. 2020年“感恩杯”台州学院第十三届大学生程序设计竞赛D、H、I题解(后续补充)

    D题:小z与他的袜子 描述 小z每天会穿一双新袜子. 开始他的衣柜里有n双袜子,袜子会从1-n进行编号.每天早上他都会从衣柜里拿编号最小的袜子来穿.每天晚上他会把今天穿的袜子扔进篮子里,如果篮子里有n ...

  8. ACM 五一杭电赛码"BestCoder"杯中国大学生程序设计冠军赛小记

    对于这项曾经热爱的竞赛,不得不说这是我最后一年参加ACM比赛了,所以要珍惜每一次比赛的机会. 五一去杭电参加了赛码"BestCoder"杯中国大学生程序设计冠军赛,去的队伍包括了今 ...

  9. 2016年中国大学生程序设计竞赛(合肥)-重现赛1001 HDU 5961

    传递 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

随机推荐

  1. HTML常用标签-手打抄录-来自-烟雨飘零-拜谢

    HTML常用标签及其全称 <a href="#">a 超级链接(anchor)</a>    <abbr title="abbreviati ...

  2. 动态规划:插头DP

    这种动归有很多名字,插头DP是最常见的 还有基于连通性的动态规划 轮廓线动态规划等等 超小数据范围,网格图,连通性 可能算是状态压缩DP的一种变式 以前我了解的状压DP用于NP难题的小数据范围求解 这 ...

  3. JVM调优总结(6):新一代的垃圾回收算法

    垃圾回收的瓶颈 传统分代垃圾回收方式,已经在一定程度上把垃圾回收给应用带来的负担降到了最小,把应用的吞吐量推到了一个极限.但是他无法解决的一个问题,就是Full GC所带来的应用暂停.在一些对实时性要 ...

  4. ② 设计模式的艺术-08.桥接(Bridge)模式

    为什么需要桥接(Bridge)模式 商城系统中常见的商品分类,以电脑为类,如何良好的处理商品分类销售的问题? 采用多层继承结构: 多层继承结构代码示例 Computer.java package co ...

  5. 最常用的8款 PHP 调试工具,你用过吗?

    Web 开发并不是一项轻松的任务,有超级多服务端脚本语言提供给开发者,但是当前 PHP 因为具有额外的一些强大的功能而越来越流行.PHP 是最强大的服务端脚本语言之一,同时也是 Web 开发者和设计者 ...

  6. js中不能做变量名的字符

    JavaScript中不能作为变量名的关键字和保留字总结: 1.js中的关键字: break case catch continue default delete do else finally fo ...

  7. 查询timestamp类型数据

    $where=" roleid = 8 and lizhi = 0 and branchid IN (".implode(",",$ids).") a ...

  8. Paramiko使用

    1.下载安装 pycrypto-2.6.1.tar.gz (apt-get install python-dev) 解压,进入,python setup.py build[编译],python set ...

  9. three.js轨道控制器OrbitControls.js

    https://blog.csdn.net/qq_37338983/article/details/78575333 文章地址

  10. python 实现字符串转整型

    def str2Int(s): l=list(s) if len(l)<=0: return 0 flag=0 sum=0 dict_num={':9} dict_tag={'+':1,'-': ...