BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
题目描述
给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少。
输入
The first line contains integer n (1 ≤ n ≤ 105), showing how many numbers the sequence has. The next line contains n integers a1, a2, ..., an (|ai| ≤ 500).
The third line contains integer m (1 ≤ m ≤ 105) — the number of queries. The next m lines contain the queries in the format, given in the statement.
All changing queries fit into limits: 1 ≤ i ≤ n, |val| ≤ 500.
All queries to count the maximum sum of at most k non-intersecting subsegments fit into limits: 1 ≤ l ≤ r ≤ n, 1 ≤ k ≤ 20. It is guaranteed that the number of the queries to count the maximum sum of at most k non-intersecting subsegments doesn't exceed 10000.
输出
For each query to count the maximum sum of at most k non-intersecting subsegments print the reply — the maximum sum. Print the answers to the queries in the order, in which the queries follow in the input.
样例输入
9 -8 9 -1 -1 -1 9 -8 9
3
1 1 9 1
1 1 9 2
1 4 6 3
样例输出
25
0
提示
In the first query of the first example you can select a single pair (1, 9). So the described sum will be 17.
Look at the second query of the first example. How to choose two subsegments? (1, 3) and (7, 9)? Definitely not, the sum we could get from (1, 3) and (7, 9) is 20, against the optimal configuration (1, 7) and (9, 9) with 25.
The answer to the third query is 0, we prefer select nothing if all of the numbers in the given interval are negative.
首先这个问题可以用费用流来解决:源点向每个点连边,容量为$1$,费用为$0$;第$i$个点向第$i+1$个点连边,容量为$1$,费用为$a_{i}$,每个点向汇点连边,容量为$1$,费用为$0$。可以知道每次增广一定是一段路径(即序列的最大连续子段和),然后将这段路径建反向边。那么我们可以模拟这个过程:每次取序列的最大连续子段和并将这一段的权值取反,假设第一次取了$[1,3]$而第二次取了$[3,5]$,那么相当于第一次取了$[1,2]$第二次取了$[4,5]$,中间的$3$在两次选取中权值抵消掉了。因为每次是贪心的取最大连续的一段,所以不会存在两次取的区间左端点或右端点相同,也就保证了每次取一个区间一定会增加一个子段。因为要取反,我们还要再维护最小连续子段和,然后在区间取反时将最大连续子段和与最小连续子段和调换一下即可。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int opt;
int l,r;
int x,k;
int ans;
int rev[400010];
struct miku
{
int x,l,r;
miku(){};
miku(int X,int L,int R){x=X,l=L,r=R;}
};
queue<miku>q;
struct Miku
{
miku smx,smn,lmx,lmn,rmx,rmn,sum;
}tr[400010];
bool operator <(miku a,miku b){return a.x<b.x;}
miku operator +(miku a,miku b){return miku(a.x+b.x,a.l,b.r);}
inline Miku pushup(Miku ls,Miku rs)
{
Miku rt;
rt.sum=ls.sum+rs.sum;
rt.smx=max(max(ls.smx,rs.smx),ls.rmx+rs.lmx);
rt.smn=min(min(ls.smn,rs.smn),ls.rmn+rs.lmn);
rt.lmx=max(ls.lmx,ls.sum+rs.lmx);
rt.lmn=min(ls.lmn,ls.sum+rs.lmn);
rt.rmx=max(rs.rmx,ls.rmx+rs.sum);
rt.rmn=min(rs.rmn,ls.rmn+rs.sum);
return rt;
}
inline void flip(int rt)
{
swap(tr[rt].smx,tr[rt].smn);
swap(tr[rt].lmx,tr[rt].lmn);
swap(tr[rt].rmx,tr[rt].rmn);
rev[rt]^=1;
tr[rt].sum.x*=-1;
tr[rt].smx.x*=-1;
tr[rt].smn.x*=-1;
tr[rt].lmx.x*=-1;
tr[rt].lmn.x*=-1;
tr[rt].rmx.x*=-1;
tr[rt].rmn.x*=-1;
}
inline void pushdown(int rt)
{
if(rev[rt])
{
rev[rt]^=1;
flip(rt<<1);
flip(rt<<1|1);
}
}
inline void build(int rt,int l,int r)
{
if(l==r)
{
scanf("%d",&x);
tr[rt].sum=tr[rt].smx=tr[rt].smn=tr[rt].lmx=tr[rt].lmn=tr[rt].rmx=tr[rt].rmn=miku(x,l,r);
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tr[rt]=pushup(tr[rt<<1],tr[rt<<1|1]);
}
inline void change(int rt,int l,int r,int k,int x)
{
if(l==r)
{
tr[rt].sum=tr[rt].smx=tr[rt].smn=tr[rt].lmx=tr[rt].lmn=tr[rt].rmx=tr[rt].rmn=miku(x,l,r);
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(k<=mid)
{
change(rt<<1,l,mid,k,x);
}
else
{
change(rt<<1|1,mid+1,r,k,x);
}
tr[rt]=pushup(tr[rt<<1],tr[rt<<1|1]);
}
inline void reverse(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
flip(rt);
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid)
{
reverse(rt<<1,l,mid,L,R);
}
if(R>mid)
{
reverse(rt<<1|1,mid+1,r,L,R);
}
tr[rt]=pushup(tr[rt<<1],tr[rt<<1|1]);
}
inline Miku query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return tr[rt];
}
pushdown(rt);
int mid=(l+r)>>1;
if(R<=mid)
{
return query(rt<<1,l,mid,L,R);
}
else if(L>mid)
{
return query(rt<<1|1,mid+1,r,L,R);
}
else
{
return pushup(query(rt<<1,l,mid,L,R),query(rt<<1|1,mid+1,r,L,R));
}
}
int main()
{
scanf("%d",&n);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
scanf("%d",&opt);
if(!opt)
{
scanf("%d%d",&k,&x);
change(1,1,n,k,x);
}
else
{
scanf("%d%d%d",&l,&r,&k);
ans=0;
while(k--)
{
Miku res=query(1,1,n,l,r);
if(res.smx.x<0)
{
break;
}
ans+=res.smx.x;
q.push(res.smx);
reverse(1,1,n,res.smx.l,res.smx.r);
}
while(!q.empty())
{
miku res=q.front();
q.pop();
reverse(1,1,n,res.l,res.r);
}
printf("%d\n",ans);
}
}
}
BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树的更多相关文章
- 【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 ...
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
- 中国大学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 ...
- PTA (Advanced Level) 1007 Maximum Subsequence Sum
Maximum Subsequence Sum Given a sequence of K integers { N1, N2, ..., NK }. A continuous su ...
- 【DP-最大子串和】PAT1007. Maximum Subsequence Sum
1007. Maximum Subsequence Sum (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...
- PAT Maximum Subsequence Sum[最大子序列和,简单dp]
1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...
- 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 ...
随机推荐
- DOM(一)
DOM可以将任何HMLT或XML文档描绘成一个由多层节点构成的结构,节点氛围几种不同的类型,每种类型分别表示文档中不同的信息及标记,每个节点都拥有各自的特点.数据和方法. Node类型 DOM1级定义 ...
- Nodejs mongoose 详解
前言 Mongoose 是在nodejs环境下,对mongodb进行便捷操作的对象模型工具.本文介绍解(翻)密(译)Mongoose插件. Schema 开始我们就要讲到Schema,一个Schema ...
- 《Python从菜鸟到高手》已经出版,开始连载了,购买送视频课程
好消息,<Python从菜鸟到高手>已经出版!!! JetBrains官方推荐图书!JetBrains官大中华区市场部经理赵磊作序!送2400分钟同步视频课程!500个案例,400道P ...
- 朱晔的互联网架构实践心得S1E5:不断耕耘的基础中间件
朱晔的互联网架构实践心得S1E5:不断耕耘的基础中间件 [下载本文PDF进行阅读] 一般而言中间件和框架的区别是,中间件是独立运行的用于处理某项专门业务的CS程序,会有配套的客户端和服务端,框架虽然也 ...
- 二十:让行内元素在div中垂直居中
(1)使用display:table-cell配合vertical-align:center(淘宝也是这样用的) <div class="method4"> <s ...
- vuex状态管理工具
父子组件之间的通信 props传递 父 向子单向传递:且每次 父组件更新时 子组件的props会跟着更新: 如果需要 子组件把数据传递给父组件,就需要在子组件上绑定自定事件 在子组件使用this ...
- 1000/problem/A
传送门: [http://codeforces.com/contest/1000/problem/A] 题意: 一个比赛颁奖,要准备T-Shirt给获奖者,但有的去年获奖过,衣服尺寸可以不改,有的需要 ...
- 软件工程(FZU2015) 赛季得分榜,第9回合
SE_FZU目录:1 2 3 4 5 6 7 8 9 10 11 12 13 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分=团队得分+个人贡献分 个人贡献分: 个人 ...
- MySQL 优化集锦
case 1: 如果筛选or条件有多个的时候,应该将最好判断的放在最前面,将最不好判断的放在最后面 比如,有一个学生表,想要找出其中年龄是20岁,住址中包含666这个数字的记录.可以下面这两个方案: ...
- bnu——GCD SUM (莫比乌斯反演)
题目:GCD SUM 题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=39872 算法:莫比乌斯反演.优化 #include<stdio.h& ...