题目链接

(BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=3836

(Codeforces) http://codeforces.com/contest/280/problem/D

题解

似乎是最广为人知的模拟费用流题目。

线段树维护DP可以做,但是合并的复杂度是\(O(k^2)\), 会TLE.

考虑做\(k\)次费用流,很容易建出一个图,中间的边容量都是1,求的是最大费用。

做费用流的过程,我们每次找一条最长路,然后将其增广,增广之后这条路的边权会取负(因为容量都是\(1\)所以要么正要么负,正反向边不同时出现)。

所以现在要做的就是每次找出和最大的一段区间然后取负,直到和全都小于\(0\)为止。

线段树维护最大、最小子段和及其位置即可。

仔细想想,每次给一段区间取负就相当于给这段区间内的元素选或者不选的状态进行反转(inverse).

也就相当于费用流的退流(反悔)。

时间复杂度\(O(kn\log n)\).

代码

BZOJ权限号到期了,所以没在上面交过。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<utility>
#include<vector>
#define pii pair<int,int>
#define mkpr make_pair
using namespace std; void read(int &x)
{
int f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
} const int N = 1e5;
int a[N+3];
vector<pii > pool;
int n,q; struct Data
{
int sum,mx,mxl,mxr,pl,pr,pml,pmr;
Data() {sum = mx = mxl = mxr = pl = pr = pml = pmr = 0;}
};
Data operator +(Data x,Data y)
{
Data ret;
ret.sum = x.sum+y.sum;
if(x.mxl>x.sum+y.mxl)
{
ret.mxl = x.mxl;
ret.pl = x.pl;
}
else
{
ret.mxl = x.sum+y.mxl;
ret.pl = y.pl;
}
if(y.mxr>x.mxr+y.sum)
{
ret.mxr = y.mxr;
ret.pr = y.pr;
}
else
{
ret.mxr = x.mxr+y.sum;
ret.pr = x.pr;
}
if(x.mx>y.mx)
{
ret.mx = x.mx;
ret.pml = x.pml; ret.pmr = x.pmr;
}
else
{
ret.mx = y.mx;
ret.pml = y.pml; ret.pmr = y.pmr;
}
if(x.mxr+y.mxl>ret.mx)
{
ret.mx = x.mxr+y.mxl;
ret.pml = x.pr; ret.pmr = y.pl;
}
return ret;
} struct SegmentTree
{
struct SgTNode
{
Data ans0,ans1; int tag;
} sgt[(N<<2)+3];
void pushup(int u)
{
sgt[u].ans0 = sgt[u<<1].ans0+sgt[u<<1|1].ans0;
sgt[u].ans1 = sgt[u<<1].ans1+sgt[u<<1|1].ans1;
}
void pushdown(int u)
{
if(sgt[u].tag)
{
swap(sgt[u<<1].ans0,sgt[u<<1].ans1);
sgt[u<<1].tag ^= 1;
swap(sgt[u<<1|1].ans0,sgt[u<<1|1].ans1);
sgt[u<<1|1].tag ^= 1;
sgt[u].tag = 0;
}
}
void build(int u,int le,int ri)
{
if(le==ri)
{
sgt[u].ans0.sum = sgt[u].ans0.mxl = sgt[u].ans0.mxr = sgt[u].ans0.mx = a[le];
sgt[u].ans0.pl = sgt[u].ans0.pr = sgt[u].ans0.pml = sgt[u].ans0.pmr = le;
sgt[u].ans1.sum = sgt[u].ans1.mxl = sgt[u].ans1.mxr = sgt[u].ans1.mx = -a[le];
sgt[u].ans1.pl = sgt[u].ans1.pr = sgt[u].ans1.pml = sgt[u].ans1.pmr = le;
return;
}
int mid = (le+ri)>>1;
build(u<<1,le,mid);
build(u<<1|1,mid+1,ri);
pushup(u);
}
void modify(int u,int le,int ri,int pos,int x)
{
if(le==pos && ri==pos)
{
sgt[u].ans0.sum = sgt[u].ans0.mxl = sgt[u].ans0.mxr = sgt[u].ans0.mx = x;
sgt[u].ans0.pl = sgt[u].ans0.pr = sgt[u].ans0.pml = sgt[u].ans0.pmr = le;
sgt[u].ans1.sum = sgt[u].ans1.mxl = sgt[u].ans1.mxr = sgt[u].ans1.mx = -x;
sgt[u].ans1.pl = sgt[u].ans1.pr = sgt[u].ans1.pml = sgt[u].ans1.pmr = le;
return;
}
pushdown(u);
int mid = (le+ri)>>1;
if(pos<=mid) modify(u<<1,le,mid,pos,x);
if(pos>mid) modify(u<<1|1,mid+1,ri,pos,x);
pushup(u);
}
void setoppo(int u,int le,int ri,int lb,int rb)
{
if(le>=lb && ri<=rb)
{
sgt[u].tag ^= 1;
swap(sgt[u].ans0,sgt[u].ans1);
return;
}
pushdown(u);
int mid = (le+ri)>>1;
if(lb<=mid) setoppo(u<<1,le,mid,lb,rb);
if(rb>mid) setoppo(u<<1|1,mid+1,ri,lb,rb);
pushup(u);
}
Data query(int u,int le,int ri,int lb,int rb)
{
if(le>=lb && ri<=rb) {return sgt[u].ans0;}
pushdown(u);
int mid = (le+ri)>>1; Data ret;
if(rb<=mid) {ret = query(u<<1,le,mid,lb,rb);}
else if(lb>mid) {ret = query(u<<1|1,mid+1,ri,lb,rb);}
else {ret = query(u<<1,le,mid,lb,rb)+query(u<<1|1,mid+1,ri,lb,rb);}
pushup(u);
return ret;
}
} sgt; int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
sgt.build(1,1,n);
scanf("%d",&q);
while(q--)
{
int opt; scanf("%d",&opt);
if(opt==0)
{
int x,y; scanf("%d%d",&x,&y);
a[x] = y; sgt.modify(1,1,n,x,y);
}
else if(opt==1)
{
int x,y,z; scanf("%d%d%d",&x,&y,&z);
int ans = 0;
for(int i=1; i<=z; i++)
{
Data cur = sgt.query(1,1,n,x,y);
// printf("delta=%d [%d,%d]\n",cur.mx,cur.pml,cur.pmr);
if(cur.mx<=0) break;
ans += cur.mx;
sgt.setoppo(1,1,n,cur.pml,cur.pmr);
pool.push_back(mkpr(cur.pml,cur.pmr));
}
printf("%d\n",ans);
for(int i=0; i<pool.size(); i++) {sgt.setoppo(1,1,n,pool[i].first,pool[i].second);}
pool.clear();
}
}
return 0;
}

BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)的更多相关文章

  1. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  2. BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)

    题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...

  3. Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]

    洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...

  4. BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  5. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...

  6. BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图

    Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢 ...

  7. Maximum Subsequence Sum【最大连续子序列+树状数组解决】

    Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i < ...

  8. 中国大学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​​ }. ...

  9. PAT1007:Maximum Subsequence Sum

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

随机推荐

  1. CNN中feature map、卷积核、卷积核的个数、filter、channel的概念解释

    CNN中feature map.卷积核.卷积核的个数.filter.channel的概念解释 参考链接: https://blog.csdn.net/xys430381_1/article/detai ...

  2. 基于FCN的图像语义分割

    语义图像分割的目标在于标记图片中每一个像素,并将每一个像素与其表示的类别对应起来.因为会预测图像中的每一个像素,所以一般将这样的任务称为密集预测.(相对地,实例分割模型是另一种不同的模型,该模型可以区 ...

  3. Jenkins的安装配置及使用

    一.以Jenkins在tomcat容器里运行的方式,jenkins的安装及安装时所涉及的JDK和tomcat的配置 1.首先下载tomcat, 2.下载Jenkins.war包,将war包放在tomc ...

  4. 大神的JS代码风格指南

    js代码风格指南:1.缩进使用空格,不要用制表符2.必须用分号3.暂时不用ES6(modules)例如export和import命令4.不鼓励(不禁止)水平对齐5.少用var 都应该使用const或者 ...

  5. Spring Boot【快速入门】简单案例

    Spring Boot[快速入门]   Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point ...

  6. 深入简出mysql--第一部分

    第二章: 1.sql分类 DDL(Data Definition Languages)语句:数据定义语言,这些语句定义了不同的数据段.数据库.表.列.索引等数据库对象的定义. 常用的语句关键字主要包括 ...

  7. Hybrid APP架构设计

    通讯 作为一种跨语言开发模式,通讯层是Hybrid架构首先应该考虑和设计的,往后所有的逻辑都是基于通讯层展开. Native(以Android为例)和H5通讯,基本原理: Android调用H5:通过 ...

  8. 批处理 使用默认浏览器 打开html文件

    @echo offfor /f "tokens=3,4" %%a in ('"reg query HKEY_CLASSES_ROOT\http\shell\open\co ...

  9. Docker架构及其三要素

    1.Docker架构 a.Docker客户端和服务端   Docker是客户-服务器(C/S)架构的程序.Docker客户端只需向Docker服务器或守护进程发出请求,服务器或守护进程将完成所有工作并 ...

  10. 生成大量插入语句,并将语句写入txt文件中

    import java.io.*; /** * Created by czz on 2019/9/23. */ public class TTest { /** * 生成大量插入语句,并将语句写入tx ...