题链:

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或者最大的子段和为负数就停止。

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

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100005
#define INF 0x3f3f3f3f
using namespace std;
int a[MAXN];
struct data{
int sval,lval,rval,sum,sl,sr,lr,rl;
void init(bool type){
if(type) lval=rval=sval=-INF;
else lval=rval=sval=+INF;
}
void reverse(){
sval*=-1; lval*=-1; rval*=-1; sum*=-1;
}
void update(const data &l,const data &r,bool type){
sum=l.sum+r.sum;
if(type)
lval=max(l.lval,l.sum+r.lval), rval=max(r.rval,r.sum+l.rval),
sval=max(max(l.sval,r.sval),l.rval+r.lval);
else
lval=min(l.lval,l.sum+r.lval), rval=min(r.rval,r.sum+l.rval),
sval=min(min(l.sval,r.sval),l.rval+r.lval); if(l.lval==lval) lr=l.lr; else lr=r.lr; if(r.rval==rval) rl=r.rl; else rl=l.rl; if(l.sval==sval) sl=l.sl,sr=l.sr;
else if(r.sval==sval) sl=r.sl,sr=r.sr;
else sl=l.rl,sr=r.lr;
}
};
struct info{
data maxi,mini;
void init(){
maxi.init(1);
mini.init(0);
}
};
struct SGT{
#define ls lson[u]
#define rs rson[u]
bool lazy[MAXN<<1];
int lson[MAXN<<1],rson[MAXN<<1],rt,sz;
info node[MAXN<<1];
void init(){
rt=sz=0;
memset(lazy,0,sizeof(lazy));
memset(lson,0,sizeof(lson));
memset(rson,0,sizeof(rson));
for(int i=0;i<(MAXN<<1);i++)
node[i].init();
}
void pushup(info &now,const info &l,const info &r){
now.maxi.update(l.maxi,r.maxi,1);//___________________维护最大连续和_1__
now.mini.update(l.mini,r.mini,0);//___________________维护最小连续和_0__
}
void pushdown(int u){
node[ls].maxi.reverse(); node[ls].mini.reverse();
node[rs].maxi.reverse(); node[rs].mini.reverse();
swap(node[ls].maxi,node[ls].mini);
swap(node[rs].maxi,node[rs].mini);
lazy[u]^=1; lazy[ls]^=1; lazy[rs]^=1;
}
void build(int &u,int l,int r){
u=++sz;
if(l==r) {
node[u].maxi=(data){a[l],a[l],a[l],a[l],l,r,r,l};
node[u].mini=(data){a[l],a[l],a[l],a[l],l,r,r,l};
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(node[u],node[ls],node[rs]);
}
void modify(int u,int l,int r,int p){
if(l==r){
node[u].maxi=(data){a[l],a[l],a[l],a[l],l,r,r,l};
node[u].mini=(data){a[l],a[l],a[l],a[l],l,r,r,l};
return;
}
if(lazy[u]) pushdown(u);
int mid=(l+r)>>1;
if(p<=mid) modify(ls,l,mid,p);
else modify(rs,mid+1,r,p);
pushup(node[u],node[ls],node[rs]);
}
void modify(int u,int l,int r,int al,int ar){
if(al<=l&&r<=ar){
node[u].maxi.reverse(); node[u].mini.reverse();
swap(node[u].maxi,node[u].mini);
lazy[u]^=1; return;
}
if(lazy[u]) pushdown(u);
int mid=(l+r)>>1;
if(al<=mid) modify(ls,l,mid,al,ar);
if(mid<ar) modify(rs,mid+1,r,al,ar);
pushup(node[u],node[ls],node[rs]);
}
info query(int u,int l,int r,int al,int ar){
if(al<=l&&r<=ar) return node[u];
info now,lnode,rnode;
now.init(); lnode.init(); rnode.init();
if(lazy[u]) pushdown(u);
int mid=(l+r)>>1;
if(al<=mid) lnode=query(ls,l,mid,al,ar);
if(mid<ar) rnode=query(rs,mid+1,r,al,ar); if(mid<al) now=rnode;
else if(ar<=mid) now=lnode;
else pushup(now,lnode,rnode);
return now;
}
#undef ls
#undef rs
}T1;
int N,M,ans;
void dfs(int k,int l,int r){
info now=T1.query(T1.rt,1,N,l,r);
if(now.maxi.sval<=0) return;
ans+=now.maxi.sval;
T1.modify(T1.rt,1,N,now.maxi.sl,now.maxi.sr);
if(k-1)dfs(k-1,l,r);
T1.modify(T1.rt,1,N,now.maxi.sl,now.maxi.sr);
}
int main()
{
//freopen("280D.in","r",stdin);
scanf("%d",&N); T1.init();
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
T1.build(T1.rt,1,N);
scanf("%d",&M);
for(int i=1,c,l,r,k;i<=M;i++){
scanf("%d",&c);
if(!c){
scanf("%d",&k); scanf("%d",&a[k]);
T1.modify(T1.rt,1,N,k);
}
else{
scanf("%d%d%d",&l,&r,&k);
ans=0;
dfs(k,l,r);
printf("%d\n",ans);
}
}
return 0;
}

●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. Android开发简易教程

    Android开发简易教程 Android 开发因为涉及到代码编辑.UI 布局.打包等工序,有一款好用的IDE非常重要.Google 最早提供了基于 Eclipse 的 ADT 作为开发工具,后来在2 ...

  2. HTTP协议以及HTTP2.0/1.1/1.0区别

    HTTP协议以及HTTP2.0/1.1/1.0区别 一.简介 摘自百度百科: 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.所 ...

  3. MongoDb进阶实践之三 MongoDB查询命令详述

    一.引言           上一篇文章我们已经介绍了MongoDB数据库的最基本操作,包括数据库的创建.使用和删除数据库,文档的操作也涉及到了文档的创建.删除.更新和查询,当然也包括集合的创建.重命 ...

  4. oracle导入命令,记录一下

    工作中用到了,这个命令,记录一下,前提要安装imp.exe imp PECARD_HN/PECARD_HN@127.0.0.1:1521/orcl file=E:\work\dmp\PECARD_HN ...

  5. Mysql主从复制架构实战

    [root@Mysql-master ~]# vim /etc/my.cnf log-bin=mysql-bin server-id = 1  #slave端server-id值改成2 mysql&g ...

  6. 20165230 2017-2018-2 《Java程序设计》第4周学习总结

    20165230 2017-2018-2 <Java程序设计>第4周学习总结 教材学习内容总结 子类与继承 通过class 子类名 extends 父类名定义子类.子类只能继承一个父类,关 ...

  7. Netty事件监听和处理(下)

    上一篇 介绍了事件监听.责任链模型.socket接口和IO模型.线程模型等基本概念,以及Netty的整体结构,这篇就来说下Netty三大核心模块之一:事件监听和处理. 前面提到,Netty是一个NIO ...

  8. Linux CentOS7.0 (03)安装验证 docker

    一.安装docker 1.升级 Linux 的软件包和内核 sudo yum update 2.安装 docker (1) sudo yum install docker  (2).验证docker安 ...

  9. Angular 学习笔记 ( CDK - Layout )

    简单说就是 js 的 media query. 1. BreakpointObserver  const layoutChanges = this.breakpointObserver.observe ...

  10. hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(2)安装hadoop

    一.依赖安装 安装JDK 二.文件准备 hadoop-2.7.3.tar.gz 2.2 下载地址 http://hadoop.apache.org/releases.html 三.工具准备 3.1 X ...