题目链接

(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. idea 设置自动生成注释

    idea新建类注释规则 /** @ProjectName: ${PROJECT_NAME} @Package: ${PACKAGE_NAME} @ClassName: ${NAME} @Descrip ...

  2. sql server isnull函数

    isnull函数 --ISNULL() 函数用于规定如何处理 NULL 值 语法:SELECT ISNULL(check_expression, replacement_value) --check_ ...

  3. 磁盘(disk)结构

  4. 关于获取jquery对象的长度

    /* 17:10 2019/8/6 @author zhangxingshuo jQuery:"write less, do more" homepage: https://jqu ...

  5. ubuntu 创建定时备份pg数据库定时任务

    ubuntu创建定时备份数据库定时任务 一.命令文件 创建db_back.sh #!/bin/bash echo "start backup" /usr/lib/postgresq ...

  6. ABAP常用函数归纳

    转至:http://blog.csdn.net/forever_crazy/article/details/17707745 获取当前逻辑系统标识:OWN_LOGICAL_SYSTEM_GET 一.日 ...

  7. AngularJs 初级入门 学习笔记

    刚学angular, 做一些笔记方便自己翻看. ng-app: 填写模块的名称 ng-init: 初始化数据(一般通过控制器初始化) ng-model: 填写数据模型 ng-bind: 绑定数据模型, ...

  8. django笔记一

    课程介绍 MVC 大部分开发语言中都有MVC框架 MVC框架的核心思想是:解耦 降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的重用 m表示model,主要用于对数据库层的封 ...

  9. linux系统很卡的基本排查方法

    1. 查看内存使用情况 free -g 当观察到free栏已为0的时候,表示内存基本被吃完了,那就释放内存吧(释放内存参考上篇文章) 2. 查看磁盘使用情况 df -h 当发现磁盘使用率很高时,那就要 ...

  10. dedecms织梦做中英文(多语言)网站步骤详解

    用dedecms织梦程序如何做中英文网站,下面是一个详细的图文教程,希望能帮助到大家. 以下是用dedecms织梦程序制作过的一个5国语言网站,下面开始教程. 一.首先在后台建栏目,有三点需要注意 1 ...