前缀和数组是十分基本和简单的一种工具,但是要想真正用好,却不容易。在平时的训练中有很多的问题都要用到前缀和。我们通过一个小的例子来看一下

cogs1190最大和

题目大意:N个数围成一圈,要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,问能形成的最大的和。

思路:一看到这个题,竟然想到了线段树,后来发现有点大材小用,要是深究的话也不是很会写,于是就另辟蹊径。这个题目中有一个神奇的关系就是这是个环,于是我们就有了两种情况:1)这一段数本身就在给定区间内;2)这一段数被分放在给定区间的两端。第一种情况比较好处理,只用前缀和,跟新最小值和最大的差就可以了;后一种情况就要用到后缀和,找到最大值和后缀和的和取最大。输出最大值就可以了。

#include<iostream>
#include<cstdio>
using namespace std;
int sum1[100001]={0},sum2[100001]={0},a[100001]={0};
int main()
{
    freopen("maxsum.in","r",stdin);
    freopen("maxsum.out","w",stdout);
    
    int n,i,j,maxn,minn;
    maxn=-2100000000;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        sum1[i]=sum1[i-1]+a[i];
    }
    for (i=n;i>=1;--i)
        sum2[i]=sum2[i+1]+a[i];
    minn=2100000000;
    for (i=1;i<=n;++i)
    {
        if (sum1[i]-minn>maxn) maxn=sum1[i]-minn;
        if (sum1[i]<minn) minn=sum1[i];    
    }
    minn=-2100000000;
    for (i=1;i<=n;++i)
    {
        if (minn+sum2[i]>maxn) maxn=minn+sum2[i];
        if (sum1[i]>minn) minn=sum1[i];
    }
    printf("%d\n",maxn);
    
    fclose(stdin);
    fclose(stdout);
}
View Code

相关文章:

猜你喜欢
  • 2022-01-05
  • 2022-12-23
  • 2021-05-29
  • 2021-07-14
  • 2021-08-15
  • 2022-12-23
  • 2021-12-08
相关资源
相似解决方案