题链:

http://codeforces.com/problemset/problem/280/D

题解:

神题,巨恶心。
(把原来的那个dp题升级为:序列带修 + 多次询问区间[l,r]内取不超过k段的不重叠子串,使得其和最大)。
按费用流的思路来看,建图方法如下:

每个点拆成两个点 i , i' ,建立超源 S和超汇 T
i -> i' : (1,a[i])
S -> i  : (1,0)
i'-> T  : (1,0)
i'-> i+1: (1,0)
那么对于某段区间,按照spfa最长路费用流去一条路一条路增广,
直到某个时候增广数==k或者增广路的费用为负数就停止。

分析其增广方式,不难发现一个重要特点(可以自己简单伪证一下哈):
每次找到增广路都是连续的一段,即对应着序列区间上和最大的连续的一段。
接下来增广操作,就会取出这一段的权值和,并把这一段的所有数全部 * -1。(就是增广后的反向边的花费)

所以就用线段树维护区间最大子段和以及最小子段和,
并且要支持单点修改和区间 * -1操作。
每次就取出[l,r]区间内的最大的子段,并把对应的子段全部 * -1,
如果取得次数==k或者最大的子段和为负数就停止。

。。。这个线段树不是一般的烦。

代码:

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #define MAXN 100005
  5. #define INF 0x3f3f3f3f
  6. using namespace std;
  7. int a[MAXN];
  8. struct data{
  9. int sval,lval,rval,sum,sl,sr,lr,rl;
  10. void init(bool type){
  11. if(type) lval=rval=sval=-INF;
  12. else lval=rval=sval=+INF;
  13. }
  14. void reverse(){
  15. sval*=-1; lval*=-1; rval*=-1; sum*=-1;
  16. }
  17. void update(const data &l,const data &r,bool type){
  18. sum=l.sum+r.sum;
  19. if(type)
  20. lval=max(l.lval,l.sum+r.lval), rval=max(r.rval,r.sum+l.rval),
  21. sval=max(max(l.sval,r.sval),l.rval+r.lval);
  22. else
  23. lval=min(l.lval,l.sum+r.lval), rval=min(r.rval,r.sum+l.rval),
  24. sval=min(min(l.sval,r.sval),l.rval+r.lval);
  25.  
  26. if(l.lval==lval) lr=l.lr; else lr=r.lr;
  27.  
  28. if(r.rval==rval) rl=r.rl; else rl=l.rl;
  29.  
  30. if(l.sval==sval) sl=l.sl,sr=l.sr;
  31. else if(r.sval==sval) sl=r.sl,sr=r.sr;
  32. else sl=l.rl,sr=r.lr;
  33. }
  34. };
  35. struct info{
  36. data maxi,mini;
  37. void init(){
  38. maxi.init(1);
  39. mini.init(0);
  40. }
  41. };
  42. struct SGT{
  43. #define ls lson[u]
  44. #define rs rson[u]
  45. bool lazy[MAXN<<1];
  46. int lson[MAXN<<1],rson[MAXN<<1],rt,sz;
  47. info node[MAXN<<1];
  48. void init(){
  49. rt=sz=0;
  50. memset(lazy,0,sizeof(lazy));
  51. memset(lson,0,sizeof(lson));
  52. memset(rson,0,sizeof(rson));
  53. for(int i=0;i<(MAXN<<1);i++)
  54. node[i].init();
  55. }
  56. void pushup(info &now,const info &l,const info &r){
  57. now.maxi.update(l.maxi,r.maxi,1);//___________________维护最大连续和_1__
  58. now.mini.update(l.mini,r.mini,0);//___________________维护最小连续和_0__
  59. }
  60. void pushdown(int u){
  61. node[ls].maxi.reverse(); node[ls].mini.reverse();
  62. node[rs].maxi.reverse(); node[rs].mini.reverse();
  63. swap(node[ls].maxi,node[ls].mini);
  64. swap(node[rs].maxi,node[rs].mini);
  65. lazy[u]^=1; lazy[ls]^=1; lazy[rs]^=1;
  66. }
  67. void build(int &u,int l,int r){
  68. u=++sz;
  69. if(l==r) {
  70. node[u].maxi=(data){a[l],a[l],a[l],a[l],l,r,r,l};
  71. node[u].mini=(data){a[l],a[l],a[l],a[l],l,r,r,l};
  72. return;
  73. }
  74. int mid=(l+r)>>1;
  75. build(ls,l,mid);
  76. build(rs,mid+1,r);
  77. pushup(node[u],node[ls],node[rs]);
  78. }
  79. void modify(int u,int l,int r,int p){
  80. if(l==r){
  81. node[u].maxi=(data){a[l],a[l],a[l],a[l],l,r,r,l};
  82. node[u].mini=(data){a[l],a[l],a[l],a[l],l,r,r,l};
  83. return;
  84. }
  85. if(lazy[u]) pushdown(u);
  86. int mid=(l+r)>>1;
  87. if(p<=mid) modify(ls,l,mid,p);
  88. else modify(rs,mid+1,r,p);
  89. pushup(node[u],node[ls],node[rs]);
  90. }
  91. void modify(int u,int l,int r,int al,int ar){
  92. if(al<=l&&r<=ar){
  93. node[u].maxi.reverse(); node[u].mini.reverse();
  94. swap(node[u].maxi,node[u].mini);
  95. lazy[u]^=1; return;
  96. }
  97. if(lazy[u]) pushdown(u);
  98. int mid=(l+r)>>1;
  99. if(al<=mid) modify(ls,l,mid,al,ar);
  100. if(mid<ar) modify(rs,mid+1,r,al,ar);
  101. pushup(node[u],node[ls],node[rs]);
  102. }
  103. info query(int u,int l,int r,int al,int ar){
  104. if(al<=l&&r<=ar) return node[u];
  105. info now,lnode,rnode;
  106. now.init(); lnode.init(); rnode.init();
  107. if(lazy[u]) pushdown(u);
  108. int mid=(l+r)>>1;
  109. if(al<=mid) lnode=query(ls,l,mid,al,ar);
  110. if(mid<ar) rnode=query(rs,mid+1,r,al,ar);
  111.  
  112. if(mid<al) now=rnode;
  113. else if(ar<=mid) now=lnode;
  114. else pushup(now,lnode,rnode);
  115. return now;
  116. }
  117. #undef ls
  118. #undef rs
  119. }T1;
  120. int N,M,ans;
  121. void dfs(int k,int l,int r){
  122. info now=T1.query(T1.rt,1,N,l,r);
  123. if(now.maxi.sval<=0) return;
  124. ans+=now.maxi.sval;
  125. T1.modify(T1.rt,1,N,now.maxi.sl,now.maxi.sr);
  126. if(k-1)dfs(k-1,l,r);
  127. T1.modify(T1.rt,1,N,now.maxi.sl,now.maxi.sr);
  128. }
  129. int main()
  130. {
  131. //freopen("280D.in","r",stdin);
  132. scanf("%d",&N); T1.init();
  133. for(int i=1;i<=N;i++) scanf("%d",&a[i]);
  134. T1.build(T1.rt,1,N);
  135. scanf("%d",&M);
  136. for(int i=1,c,l,r,k;i<=M;i++){
  137. scanf("%d",&c);
  138. if(!c){
  139. scanf("%d",&k); scanf("%d",&a[k]);
  140. T1.modify(T1.rt,1,N,k);
  141. }
  142. else{
  143. scanf("%d%d%d",&l,&r,&k);
  144. ans=0;
  145. dfs(k,l,r);
  146. printf("%d\n",ans);
  147. }
  148. }
  149. return 0;
  150. }

●CodeForces 280D k-Maximum Subsequence Sum的更多相关文章

  1. 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 01-复杂度2 Maximum Subsequence Sum (25分)

    01-复杂度2 Maximum Subsequence Sum   (25分) Given a sequence of K integers { N​1​​,N​2​​, ..., N​K​​ }. ...

  2. PAT1007:Maximum Subsequence Sum

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  3. PTA (Advanced Level) 1007 Maximum Subsequence Sum

    Maximum Subsequence Sum Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous su ...

  4. 【DP-最大子串和】PAT1007. Maximum Subsequence Sum

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  5. PAT Maximum Subsequence Sum[最大子序列和,简单dp]

    1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...

  6. PAT甲 1007. Maximum Subsequence Sum (25) 2016-09-09 22:56 41人阅读 评论(0) 收藏

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  7. PAT 甲级 1007 Maximum Subsequence Sum (25)(25 分)(0不是负数,水题)

    1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...

  8. PAT 1007 Maximum Subsequence Sum(最长子段和)

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  9. pat1007. Maximum Subsequence Sum (25)

    1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  10. PTA 01-复杂度2 Maximum Subsequence Sum (25分)

    题目地址 https://pta.patest.cn/pta/test/16/exam/4/question/663 5-1 Maximum Subsequence Sum   (25分) Given ...

随机推荐

  1. Beta阶段敏捷冲刺报告-DAY1

    Beta阶段敏捷冲刺报告-DAY1 Scrum Meeting 敏捷开发日期 2017.11.2 讨论时间 20:30 讨论地点 下课路上以及院楼侧门 参会人员 项目组全体成员 会议内容 附加功能讨论 ...

  2. 20162330 第10周 MySort实验

    关于MySort的进一步实践 课堂作业题目如下: 模拟实现Linux下Sort -t : -k 2的功能.参考Sort的实现.提交码云链接和代码运行截图. import java.util.*; pu ...

  3. 201621123050 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 答:接口.has-a.comparable 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. ...

  4. 基于scrapy爬虫的天气数据采集(python)

    基于scrapy爬虫的天气数据采集(python) 一.实验介绍 1.1. 知识点 本节实验中将学习和实践以下知识点: Python基本语法 Scrapy框架 爬虫的概念 二.实验效果 三.项目实战 ...

  5. Digilent Xilinx USB Jtag cable

    Digilent Xilinx USB Jtag cable 安装环境 操作系统:fedora 20 64bit 源链接:https://wiki.gentoo.org/wiki/Xilinx_USB ...

  6. Environment.getExternalStorageDirectory()

    Environment.getExternalStorageDirectory()得到的是storage/emulated/0

  7. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  8. Java 多线程 从无到有

    个人总结:望对屏幕对面的您有所帮助 一. 线程概述 进程: 有独立的内存控件和系统资源 应用程序的执行实例 启动当前电脑任务管理器:taskmgr 进程是程序(任务)的执行过程,它持有资源(共享内存, ...

  9. JavaScript查找数组中最大的值

    // 查找一个数组中最大的数 // 定义一个方法 searchMax function searchMax(arr) { // 声明一个变量MaxNumber假设为数组中最大的值arr[0]; var ...

  10. c 语言typedef 和 define的使用和区别

    #define是C的指令,用于为各种数据类型定义别名,与typedef 类似,但是有一下几点不同 1,typedef仅限于为类型定义符号名称,而#define不仅可以为类型定义符号名称,也能为数值定义 ...