51Nod1050 循环数组最大子段和

Problem

N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。

Solution

最大字段和最大,或者去掉中间某个最小字段和剩下的最大。

Code

#include<stdio.h>
#include<set>
#include<iostream>
#include<algorithm>
typedef long long ll;
typedef long double ld;
typedef double db;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int n;
ll a[50020];
ll fmn[50020],fmx[50020],mn=0,mx=0,sum;
int main() {
    io_opt;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
        fmx[i]=max(a[i],fmx[i-1]+a[i]);
        mx=max(mx,fmx[i]);
        fmn[i]=min(a[i],fmn[i-1]+a[i]);
        mn=min(mn,fmn[i]);
    }
    cout<<max(mx,sum-mn);
    return 0;
}

原文地址:https://www.cnblogs.com/sz-wcc/p/11727716.html

时间: 2024-10-09 11:24:20

51Nod1050 循环数组最大子段和的相关文章

51nod 1050 循环数组最大子段和【环形DP/最大子段和/正难则反】

1050 循环数组最大子段和 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题  收藏  关注 N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列).当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13.和为20. Input 第1

1050 循环数组最大子段和

个整数组成的循环序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列).当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13.和为20. Input 第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数 (-10^9 <= S[i] <

循环数组最大子段和(动态规划思想的巧妙转换)

个人心得:这是一道好题,线性的最大字段和在动态规划中是司空见惯的.所以对于这种动态规划的思想的巧妙转变也是需要 锻炼的,就像在暑假集训里面碰到的从1到k是递增,k到n是递减的k使得此时的和最大,当时也是毫无办法,虽然后面 想到了分别将首尾展开然后分别求递增的最大和,题目就迎刃而解了.其实这一题题目的分解还是很明白的, 最大值无非就是线性动态规划和横跨俩端的子段,横跨俩端的子段最简单就是俩层循环很明显超时了,后面想着从左边找到最大 的并标志,但是很明显俩段最大值不一定是在一段最大值的前提下,所以后

51Nod 1050 循环数组最大子段和 | DP

Input示例 6 -2 11 -4 13 -5 -2 Output示例 20 分析: 有两种可能,第一种为正常从[1 - n]序列中的最大子字段和:第二种为数组的total_sum - ([1-n]序列中的最短序列和) 最后结果为 max { 第一种, 第二种}. 对于第二种: 循环数组求最大子段和,可能出现中间的一部分不要,要两边的数.比如:-1 4 -1 -5 5 -2 1 -1 3,他的最大子段和就为 左边的-1 4加上右边的5 -2 1 -1 3,也就是,去掉1 -5这一段后的结果.而

51NOD1050 循环数组最大字段和

N个整数组成的循环序列a11,a22,a33,…,ann,求该序列如aii+ai+1i+1+…+ajj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1n−1,ann,a11,a22这样的序列).当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13.和为20. Input第1行:整数序列的长度N(2 <= N <= 50000) 第2 - N+1行:N个整数 (-10^9 <= Sii <= 10^9)O

[51NOD1959]循环数组最大子段和(dp,思路)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 这道题的最大子段和有两种可能,一种是常规的子段和,另一种是从结尾到开头的一个子段.常规做是一种可能,另一种带循环的则可以认为是序列中间有一段最小子段和,把这段最小子段和去掉,剩下的可能就是最大子段和了. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL;

51nod 1050 循环数组最大子段和

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1050 题意: 思路: 情况无非分为两种: ①正常的最大子段和. ②首尾相连的最大子段和,此时中间的那段肯定是最小子段和,用总的sum-最小子段和即可. 最后比较两者大小. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

循环数组最大子段和

记得以前好像做过,应该是学长给了个思路才想出来的,明明是一道水题,写了半天全是错的,给自己留个纪念吧,思路很简单:把数组复制一遍接到数组后面,先求最大值 ,要是直接求的话肯定错,个数要限制一下,给个例子:4 5 6 7 ,复制之后是 4 5 6 7 4 5  6 7 要是没有个数限制的话就全加上了,之后这个先来一个候选值,因为不一定对 例子是: 1 2 3  -5 3  2 1,自己跑一遍的话可以知道是3 + 2 + 1 + 1 + 2 + 3之前写的会全加上,这个就要另一个思路了,就是反其道而

51nod 1050 循环数组最大子段和 (dp)

http://www.51nod.com/onlineJudge/questionCode.html#problemId=1050&noticeId=13385 参考:http://blog.csdn.net/acdreamers/article/details/38760805 #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; int n; ll a[100001