最大K段和(FZSZ多校模拟)

题目

给出N个数,在里面选出不超过K段连续的子序列,使其两两不相交,求总和的最大值(可以一段都不选)

数据范围

N,K<= 100000

对于一个数a满足 -1000000000 <= a <= 100000000

 

题解

首先看到这道题很容易想到是dp,然后再加上一个优化

可是这里的N,K太大O(NK)是会超时的

所以换方法,然后用了一种不知道为什么的算法:

用线段树维护,然后每次选出最大的一段子序列,加入答案中,再将这段区间选的数都乘上-1,一直重复K次或者是选到了最大的子序列是负数时,就退出

好像是用到了费用流的思想,然而我并想不出来

所以只会简单的证明一下

证明:每次取得的区间只有两种可能:

1.被之前选的区间之内

2.选择一个还未选择过的区间(这里指的是从左端点到右端点一直没有被选过)

证明

首先一段区间两端一定都是正数(对于当前来说)

对于当前情况

如果有一个区间i与之前选过的区间j相交,那么有一个端点是在之前选过的区间之内,且这个端点的值一定是正数

也不难发现,与之前选过的区间相交的这一段区间的和一定是大于0的,那就是说之前这个端点的值是负数,且相交区间和的应该是负数,那么在第一次选这个j的时候时就可以选择不要相交的区间,会使和最大,反证法可得命题不成立所以不会相交

同时i包含j也可以用反证法证明

代码

#include <iostream>//对于这道题,首先是要维护区间最大值最小值,同时也要维护从最左端开始的最大
#include <cstdio>//与最小区间,右端点也要这样,才可以进行转移
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
#define ll long long
const int MAXN = 1e5 + 3;
struct edge{
    int l ,r;
    ll sum;
    edge(){}
    edge( int L , int R , ll S ){
        l = L;r 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值