环状最大两段子段和题解

环状最大两段子段和(maxsum2)

【问题描述】

给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大。

【输入文件】

输入文件maxsum2.in的第一行是一个正整数N,表示了序列的长度。

第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列,第一个数和第N个数是相邻的。

【输出文件】

输入文件maxsum2.out仅包括1个整数,为最大的两段子段和是多少。

【样例输入】

7

2 -4 3 -1 2 -4 3

【样例输出】

9

【样例说明】

一段为3 –1 2,一段为3 2

【数据规模与约定】

对于40%的数据,有2 ≤ N ≤ 2000。

对于100%的数据,有N ≤ 200000。

题解:

1、f[i]记录从左至右到i前最大子段和;

2、g[i]记录从右至左到i后最大子段和;

3、枚举i求max(f[i]+g[i+1]),记录为maxans;

4、f[i]记录从左至右到i前最小子段和;

5、g[i]记录从右至左到i后最小子段和;

6、枚举i求min(f[i],g[i+1]),记录为minans;

7、枚举i记录a[i]之和为sum;

8、答案ans为max(max,sum-minans)。

View Code
var tmp,f,g,ff,gg,a:array[0..200001]of longint;
    n,i,max,min,sum:longint;

begin
  assign(input,'maxsum2.in'); reset(input);
  assign(output,'maxsum2.out'); rewrite(output);
  read(n); sum:=0;
  for i:=1 to n do
  begin
    read(a[i]); inc(sum,a[i]);
  end;
  max:=-maxlongint;
  for i:=1 to n do
  begin
    if tmp[i-1]<0 then tmp[i]:=a[i] else
      tmp[i]:=tmp[i-1]+a[i];
    if tmp[i]>max then max:=tmp[i];
    f[i]:=max;
  end;
  max:=-maxlongint;
  for i:=n downto 1 do
  begin
    if tmp[i+1]<0 then tmp[i]:=a[i] else
      tmp[i]:=tmp[i+1]+a[i];
    if tmp[i]>max then max:=tmp[i];
    g[i]:=max;
  end;
  max:=-maxlongint;
  for i:=1 to n-1 do
    if f[i]+g[i+1]>max then max:=f[i]+g[i+1];
  min:=maxlongint;
  for i:=1 to n do
  begin
    if tmp[i-1]>0 then tmp[i]:=a[i] else
      tmp[i]:=tmp[i-1]+a[i];
    if tmp[i]<min then min:=tmp[i];
    f[i]:=min;
  end;
  min:=maxlongint;
  for i:=n downto 1 do
  begin
    if tmp[i+1]>0 then tmp[i]:=a[i] else
      tmp[i]:=tmp[i+1]+a[i];
    if tmp[i]<min then min:=tmp[i];
    g[i]:=min;
  end;
  min:=maxlongint;
  for i:=1 to n-1 do
    if f[i]+g[i+1]<min then min:=f[i]+g[i+1];
  if (max>sum-min)or(sum=min) then writeln(max) else writeln(sum-min);
  close(input); close(output);
end.

转载于:https://www.cnblogs.com/haipzm/archive/2012/08/02/2619443.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值