$n \leq 50000$的序列,问选不超过$m \leq 50000$个区间使得和最大。

如果正数区间总数比$m$小那肯定全选。否则有两种方式减少区间数量:丢掉一个正区间;补一个负区间连接两个正区间。贪心即可。

先把左右端的负数去掉,然后把正区间和负区间处理出来。优先队列维护区间值,然后开个链表模拟合并(删左右,改自己)。注意删右边时调整右端点。

  1. //#include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. //#include<time.h>
  5. //#include<complex>
  6. //#include<set>
  7. #include<queue>
  8. //#include<vector>
  9. #include<algorithm>
  10. #include<stdlib.h>
  11. using namespace std;
  12.  
  13. #define LL long long
  14. int qread()
  15. {
  16. char c; int s=,f=; while ((c=getchar())<'' || c>'') (c=='-') && (f=-);
  17. do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s*f;
  18. }
  19.  
  20. //Pay attention to '-' , LL and double of qread!!!!
  21.  
  22. int n,m;
  23. #define maxn 50011
  24. #define LL long long
  25.  
  26. LL Abs(LL x) {return x>?x:-x;}
  27.  
  28. int a[maxn]; LL sum[maxn];
  29. int b[maxn],lb,ll[maxn],rr[maxn]; bool vis[maxn];
  30. struct qnode
  31. {
  32. LL v; int id;
  33. bool operator > (const qnode &b) const {return v>b.v;}
  34. };
  35. priority_queue<qnode,vector<qnode>,greater<qnode> > q;
  36. int main()
  37. {
  38. n=qread(); m=qread();
  39. for (int i=;i<=n;i++) a[i]=qread();
  40. {
  41. int L=,R=n; while (a[L]<=) L++; while (a[R]<=) R--;
  42. for (int i=L,j=;i<=R;i++,j++) a[j]=a[i];
  43. n=R-L+; a[n+]=;
  44. }
  45. for (int i=;i<=n;i++) sum[i]=sum[i-]+a[i];
  46.  
  47. LL ans=;
  48. int cnt=;
  49. {
  50. LL tmp=a[],last=;
  51. for (int i=;i<=n+;i++)
  52. {
  53. if (tmp> && a[i]<=)
  54. {
  55. b[++lb]=last;
  56. q.push((qnode){tmp,lb});
  57. ans+=tmp; cnt++; tmp=a[i]; last=i;
  58. }
  59. else if (tmp> && a[i]>) tmp+=a[i];
  60. else if (tmp<= && a[i]>)
  61. {
  62. b[++lb]=last;
  63. q.push((qnode){-tmp,lb});
  64. tmp=a[i]; last=i;
  65. }
  66. else tmp+=a[i];
  67. }
  68. }
  69.  
  70. for (int i=;i<=lb+;i++) ll[i]=i-,rr[i]=i+; b[lb+]=n+;
  71. if (cnt<=m) {printf("%lld\n",ans); return ;}
  72. while (m<cnt--)
  73. {
  74. while (vis[q.top().id]) q.pop();
  75. ans-=q.top().v; int now=q.top().id; q.pop();
  76.  
  77. if (ll[now]==)
  78. {
  79. vis[rr[now]]=;
  80. vis[now]=;
  81. int u=rr[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now];
  82. ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u];
  83. }
  84. else if (rr[now]==lb+)
  85. {
  86. vis[ll[now]]=;
  87. vis[now]=;
  88. int u=ll[now]; ll[rr[now]]=ll[now]; rr[ll[now]]=rr[now];
  89. ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u]; b[lb+]=b[u];
  90. }
  91. else
  92. {
  93. int L=b[ll[now]],R=b[rr[rr[now]]]-;
  94. vis[ll[now]]=; vis[rr[now]]=; int u=ll[now],v=rr[now];
  95. b[now]=L; q.push((qnode){Abs(sum[R]-sum[L-]),now});
  96. ll[rr[u]]=ll[u]; rr[ll[u]]=rr[u];
  97. ll[rr[v]]=ll[v]; rr[ll[v]]=rr[v];
  98. }
  99. }
  100.  
  101. printf("%lld\n",ans);
  102. return ;
  103. }

51nod1053 最大M子段和 V2的更多相关文章

  1. 51Nod1053 最大M子段和V2 二分+DP

    传送门 直接DP的话最多也只能做到\(O(nm)\),对于\(5\times 10^4\)的数据范围实在无能为力 夹克老爷提供的做法是贪心,思想大概是在调整的同时,合理构造每个选择对应的新状态,使得新 ...

  2. 最大M子段和 V2

    51nod1053 这题还是我们熟悉的M子段和,只不过N,M<=50000. 这题似乎是一个堆+链表的题目啊 开始考虑把所有正数负数锁在一起. 比如: 1 2 3 -1 –2 -3 666 缩成 ...

  3. 51nod 1053 最大M子段和 V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],将这N个数划分为互不相交的M个子段,并且这M个子段的和是最大的.如果M >= N个数中正数的个数,那么输出所有正数的和. 例如:-2 ...

  4. [51nod1254]最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  5. 51nod 1254 最大子段和 V2 ——单调栈

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  6. 51nod 1254 最大子段和 V2

    N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...

  7. 51nod1524 最大子段和V2

    题干 N个整数组成的序列a[1],a[2],a[3],-,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数 ...

  8. 51nod1254 最大子段和 V2 DP

    ---题面--- 题解: 表示今天做题一点都不顺.... 这题也是看了题解思路然后自己想转移的. 看的题解其实不是这道题,但是是这道题的加强版,因为那道题允许交换k对数. 因为我们选出的是连续的一段, ...

  9. 51Nod 最大M子段和系列 V1 V2 V3

    前言 \(HE\)沾\(BJ\)的光成功滚回家里了...这堆最大子段和的题抠了半天,然而各位\(dalao\)们都已经去做概率了...先%为敬. 引流之主:老姚的博客 最大M子段和 V1 思路 最简单 ...

随机推荐

  1. 程序windows上可以上传附件,部署到 linux服务器后出现 “上传目录 不可写” 怎么解决?

    这样的问题一般都是linux  下文件读写权限引起的,用 shell  命名到上传附件的目录(如 cd /data/www/project/upload/),然后执行 shell 文件权限设置: 例如 ...

  2. mvc的model验证,ajaxhelper,验证机制语法

    ajaxhelper: onsuccess是调用成功后显示方法,还有一个方法是调用前显示 model验证: 控件前端验证: 需要引入的JS 其中第二个是ajaxhelper的必须验证 后台的两个同名不 ...

  3. 如何启动Intel VT-x

    如何启动Intel VT-x 5 在64bit win7系统下安装了Vmware10,然后安装64位的UbuntuKylin 14.04,想要打开UbuntuKylin,弹出如下对话框: 请问该如何启 ...

  4. python基础一 day10(2)

    复习: # 三元运算符# 接收结果的变量 = 条件为真的结果 if 条件 else 条件为假的结果# 接收结果的变量 = “真结果” if 条件 else “假结果”## 命名空间 和 作用域# 三种 ...

  5. Python字符编码及字符串

    字符编码 字符串是一种数据类型,但是字符串比较特殊的是编码问题,计算机只能处理数字,处理文本就需要将文本转换成数字. 计算机设计时8bit作为一个字节byte,一个字节能表示的最大整数就是(2^8)- ...

  6. WINDOWS-API:取得系统语言种类-GetOEMCP

    GetOEMCP VB声明 Declare Function GetOEMCP Lib "kernel32" Alias "GetOEMCP" () As Lo ...

  7. 用Kotlin开发android平台语音识别,语义理解应用(olamisdk)

    Kotlin是由JetBrains创建的基于JVM的编程语言,IntelliJ正是JetBrains的杰作,而android Studio是 基于IntelliJ修改而来的.Kotlin是一门包含很多 ...

  8. Mac OS 终端强化美化:iterm2 + zsh + oh~my~zsh 设置教程

    为了获得更好的排版效果,文章改用markdown撰写,故重发一次. 前言 mac自带的terminal终端没有文件名高亮等功能,而且界面不是很好看,故今晚学舍友折腾了终端,可以让自己使用起来更加方便, ...

  9. 文件操作-mkdir

    Linux mkdir命令 主要用来创建目录,也可以直接创建多层目录,本文就为大家介绍下 Linux mkdir命令 . 转载自https://www.linuxdaxue.com/linux-com ...

  10. Python列表,元组,字典,集合详细操作

    菜鸟学Python第五天 数据类型常用操作及内置方法 列表(list) ======================================基本使用====================== ...