最长连续子序列变种

在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 n 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币。但是这个游戏比较坑,里面竟然有负数,表示你要支付多少蒜币。因为这些数字都是可见的,所以大家都是不会出现的赔的情况。
游戏规则:每人只能抓一次,只能抓取一段连续的纸团,所有纸团上的数字和就是你可以获得的蒜币。
蒜头君作为蒜厂的一员在想,我怎么可以获得最多的蒜币呢?最多能获取多少蒜币呢?
因为年会是发奖,那么一定有大于 0 的纸团。
输入格式
第一行输入一个整数 n,表示有 n 个纸团。
第二行输入输入 n 个整数 ai表示每个纸团上面写的数字(这些纸团的输入顺序就是环形桌上纸团的摆放顺序)。
输出格式
输出一个整数,表示蒜头君最多能获取多少蒜币。
只过了6组数据:https://paste.ubuntu.com/p/Fc6xmf8F7Z/


本题成环了,连续的子序列最大值,当不成环的时候,取得最大值的时候可能在中间的连续部分,在当成环之后,就多了一种在两端的可能,那么这种连续子序列的最大值求法就可以用总和减去中间最小的连续子序列的和。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6;
ll a[maxn]; 
ll dp_max[maxn];
ll dp_min[maxn];
int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int n;
	while(scanf("%d",&n)!=EOF){
		 ll sum=0;
		for(int i=1;i<=n;++i){
			scanf("%lld",&a[i]);
			sum+=a[i];
		}
		ll MAX=-maxn;
		ll MIN=maxn;
		dp_min[0]=dp_max[0]=0;
		for(int i=1;i<=n;++i){
					MAX=max(MAX,dp_max[i]=max((ll)0,max(a[i],dp_max[i-1]+a[i])));
					MIN=min(MIN,dp_min[i]=min((ll)0,min(a[i],dp_min[i-1]+a[i])));
		}
		cout<<max(MAX,sum-MIN)<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值