题目描述

给一列数,要求支持操作: 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
9 -8 9 -1 -1 -1 9 -8 9
3
1 1 9 1
1 1 9 2
1 4 6 3

样例输出

17
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采花——模拟费用流+线段树的更多相关文章

  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. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

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

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

  5. PAT1007:Maximum Subsequence Sum

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

  6. 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 ...

  7. 【DP-最大子串和】PAT1007. Maximum Subsequence Sum

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

  8. PAT Maximum Subsequence Sum[最大子序列和,简单dp]

    1007 Maximum Subsequence Sum (25)(25 分) Given a sequence of K integers { N~1~, N~2~, ..., N~K~ }. A ...

  9. 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 ...

随机推荐

  1. rabbitMQ教程(五)rabbitmq 指令 以及解决web管理界面无法使用guest用户登录

    安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号guest登陆管理控制台,却提示登陆失败. 翻看官方的release文档后,得知由于账号gues ...

  2. vscode 缩进改为2空格

    因为vscode默认启用了"editor.detectIndentation": true”根据文件类型自动设置tabsize的选项. 在配置中加上 "editor.de ...

  3. OO生存指.....抱歉无法生存

    还记得前三次的设计策略:星期二之前实现功能,星期三找一下可能出现的小bug. 这三次以及变成了:星期二之前能跑出来就行. 总体来说设计策略是:先让几个线程能够顺利运行,再开始实现功能. 在接触到多线程 ...

  4. 亲测可以永久破解2018版本的pycharm

    pycharm是很强大的开发工具,但是每次注册着实让人头疼.网络上很多注册码.注册服务器等等.但都只是一年或者不能用:为次有如下解决方案.亲测有效!!! 如果想让pycharm永久被激活,比如截止日到 ...

  5. 日志之环绕通知(AOP)

    环绕通知:一个完整的try...catch...finally结构 编写环绕通知方法,环绕通知需要携带ProceedingJoinPoint 这个类型的参数,ProceedingJoinPoint类型 ...

  6. PS调出冷绿色电影画面风格

    原图 一.按照惯例先磨皮,我修照片的习惯是,先拉一层色阶,使直方图平均分配,画面会显得没那么灰,当然,这只是个人喜好,先加后加都没所谓. 二.由于脸部的亮度不够,显得有点脏.所以这一步主要是通过拉曲线 ...

  7. iRate---一个跳转AppStore评分弹窗

    https://www.aliyun.com/jiaocheng/357479.html 摘要:gitHub地址:https://github.com/nicklockwood/iRate可以通过配置 ...

  8. net core 小坑杂记之配置文件读取 02 (控制器里读)

    上次更新博客的时候提到了如何在EF的上下文里读取配置,这次介绍一下在控制器里如何读取. 先说一种简单易懂的: 首先以键值对的形式在appsettings里添加一条配置信息,接着Startup里注入配置 ...

  9. 替换iframe的内容

    一般就是点个按钮然后在不跳转页面的情况下显示另外一个页面的内容,显示的速度比较快,ifream还算是常用的吧 用的时候实现方式有以下几种, 1.替换src路径(觉得麻烦,没接触过,就不这样干了) 2. ...

  10. mybatis插入数据并返回自增Id

    上图mybatis的写法,在xxxMapper.xml中: 加入:useGeneratedKeys="true" keyProperty="applyId" k ...