http://ayit.acmclub.com/index.php?app=problem_title&id=233&problem_id=21816
最大字段和的变形,圆环的最大字段和有两种可能。1、如果最大字段和包含开头和结尾,那么最小字段和一定被最大字段和包围在最中间。2、如果最大字段和不同时包含开头和结尾,只需求出最大字段和即可。
求出以上两种情况的最小字段和 和 最大字段和。然后用总和 减去最小字段和 和 最大字段和进行比较即可,找到较大的值即可。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<limits.h>
using namespace std;
long long maxx(long long a,long long b,long long c )
{
a = a>b?a:b;
a = a>c?a:c;
return a;
}
long long minn(long long a,long long b,long long c)
{
a = a<b?a:b;
a = a<c?a:c;
return a;
}
long long dfs_max(int a[],int left,int right)
{
long long i,m,lmax,rmax,sum;
if(left == right) return a[left];
m = (left + right)/2;
lmax = sum = 0;
for(i = m; i >= left; i--)
{
sum += a[i];
lmax = lmax>sum?lmax:sum;
}
rmax = sum = 0;
for(i = m+1; i <= right;i++)
{
sum += a[i];
rmax = rmax>sum?rmax:sum;
}
return maxx(lmax+rmax,dfs_max(a,left,m),dfs_max(a,m+1,right));
}
long long dfs_min(int a[],int left,int right)
{
long long i,m,lmin,rmin,sum;
if(left == right) return a[left];
m = (left + right)/2;
lmin = 0;
sum = 0;
for(i = m; i >= left; i--)
{
sum += a[i];
lmin = lmin<sum?lmin:sum;
}
rmin = 0;
sum = 0;
for(i = m+1; i <= right;i++)
{
sum += a[i];
rmin = rmin<sum?rmin:sum;
}
return minn(lmin+rmin,dfs_min(a,left,m),dfs_min(a,m+1,right));
}
int main()
{
int N,n,a[50010];
long long sum;
while(scanf("%d",&n) != EOF)
{
sum = 0;
memset(a,0,sizeof(a));
for(int i = 0; i < n; i++)
{
scanf("%d",&a[i]);
sum+= a[i];
}
long long max0 = dfs_max(a,0,n-1);
long long min0 = dfs_min(a,0,n-1);
printf("%lld\n",(sum - min0)>max0?(sum - min0):max0);
}
return 0;
}
本文探讨了最大字段和的变形问题,包括如何求出最大字段和与最小字段和,以及通过比较总和与最小最大字段和来找出较大值的方法。
235

被折叠的 条评论
为什么被折叠?



