BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)
题目链接
(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 (模拟费用流、线段树)的更多相关文章
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)
题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...
- Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]
洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...
- BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
- 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时间中选出一个时间进行抢劫,并计划抢 ...
- Maximum Subsequence Sum【最大连续子序列+树状数组解决】
Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i < ...
- 中国大学MOOC-陈越、何钦铭-数据结构-2015秋 01-复杂度2 Maximum Subsequence Sum (25分)
01-复杂度2 Maximum Subsequence Sum (25分) Given a sequence of K integers { N1,N2, ..., NK }. ...
- PAT1007:Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
随机推荐
- 洛谷P1192台阶问题
题目描述 有NN级的台阶,你一开始在底部,每次可以向上迈最多KK级台阶(最少11级),问到达第NN级台阶有多少种不同方式. 输入格式 两个正整数N,K. 输出格式 一个正整数,为不同方式数,由于答案可 ...
- 用python操作mysql数据库
数据库的安装和连接 PyMySQL的安装 pip install PyMySQL python连接数据库 import pymysql db = pymysql.connect("数据库ip ...
- Django创建数据库常用字段及参数
Django创建数据库常用字段及参数 常用字段 1.models.AutoField 自增列= int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列 ...
- Keras模型训练的断点续训、早停、效果可视化
训练:model.fit()函数 fit(x=None, y=None, batch_size=None, epochs=, verbose=, callbacks=None, validation_ ...
- Postman之简单使用
前提:已获得接口文档 / 抓包数据 1.启动Postman 直接在这个页面输入数据(不用管其他的地方!!!) 2.按照接口文档填入 注意蓝色框中的数据 请求方式:POST(几乎都是使用POST/GET ...
- leecode100热题 HOT 100(2)
# 题名 题解 通过率 难度 出现频率 142 环形链表 II 43.3% 中等 146 LRU缓存机制 43.3% 中等 148 排序链表 ...
- Global.asax文件
转载:http://www.cnblogs.com/I-am-Betty/archive/2010/09/06/1819558.html 概述: Global.asax文件也叫做asp.net应用程序 ...
- 第一章 T-SQL查询和编程基础 T-SQL语言基础(1)
T-SQL查询和编程基础(1) 1.1 理论背景 SQL是为查询和管理关系型数据库管理系统(RDBMS)中的数据而专门设计的一种标准语言. RDBMS是一种基于关系模型的数据库管理系统,关系模型则是一 ...
- N1试卷常考词汇总结
免れる まぬがれる 免去,幸免 軽率 けいそつ 轻率,草率 捩れる ねじれる 拧劲儿,扭歪,弯曲 裂ける さける 裂开,破裂 避ける さける 躲避,避开 つまむ 挟,捏,掐 追及 ついきゅう 追上.追 ...
- VMware安装CentOS6.3
这里测试的是 CentOS-6.3-x86_64-bin-DVD1 链接:点击进入提取码: zs32 如果这里CentOS下载太慢的话 点击进入下载