最大子段和
問題描述
給出乙個首尾相連的迴圈序列,從中找出連續的一段,使得該段中的數和最大。
輸入格式
第一行乙個整數 n, 表示有 n 個數。( 1<=n<=100000)
第二行有 n 個整數,每個數的絕對值不超過 100000.
輸入樣例
4
2 -4 1 4
輸出樣例
7
我們用sum[l,r]表示[l,r]的區間和
對於這道題目,有幾個值得思考的結論
①如果不是首尾相連的循壞序列,那麼最大子段和的子段[l,r]中對於任意的l,mid,sum[l,mid]>=0
證明:
如果存在[l,mid]<0,那麼最大子段和可以更新成sum[l,r]-sum[l,mid]>sum[l,r]
②如果是首尾相連的迴圈序列,那麼最大子段和=max(sum[1,n]-最小子段和,sum[1,n])
簡單來講這個結論就是
當最小子段和》=0時,最大子段和=sum[1,n]
當最小子段和<0時,最大子段和=sum[1,n]-最小子段和
證明: 當 最小子段和》=0 時就表示當前數列中所有值非負,自然而然最大子段和就是整個區間之和
當 最小子段和<0 時:
如果存在多個小於0的子段和,那麼我們選擇最小的
例如 sum[a,b]=0,所以sum[a,d]=sum[a,b]+sum[b+c]>sum[a,b]
因此sum[a,d]的最大轉圈(迴圈)子段和=sum[a,d]-sum[a,b]
而如果sum[1,n]減去其它的任意負子段和,增加的值都不如減去最小子段和多
因此對於這道題,我們的做法如下
①求出最大不迴圈子段和(sum<0就重新計數)
②求出最小不迴圈子段和(sum>0就重新計數)
③記錄最大的單個值
④記錄整個區間的和
當最大不迴圈子段和==0,那麼輸出最大單值
否則輸出max(最大不迴圈子段和,整個區間和-最小不迴圈子段和)
#include
#include
using
namespace
std;
inline
long
long input()
long
long x,zheng,fu,res_z,res_f,sum=0,all_fu=-987654321;
//rez_z記錄最大不迴圈子段和,res_f記錄最小不迴圈子段和的相反數
//zheng記錄當前子段最大和,fu記錄當前子段最小和的相反數
//sum記錄所有值之和
//all_fu記錄最大單值(在所有值都為負時輸出)
int main()
printf("%lld",res_z>0?max(res_z,sum+res_f):all_fu);
}
最大子段和
設a 是n個整數的序列,稱為該序列的子串行,其中1 i j n.子串行的元素之和稱為a的子段和.例如,a 2,11,4,13,5,2 那麼它的子段和是 長度為1的子段和 2,11,4,13,5,2 長度為2的子段和 9,7,9,8,7 長度為3的子段和 5,20,4,6 長度為4的子段和 18,15...
最大子段和
問題表述 n個數 可能是負數 組成的序列a1,a2,an.求該序列 例如 序列 2,11,4,13,5,2 最大子段和 11 4 13 20。1 窮舉演算法 o n3 o n2 2 分治法 將序列a 1 n 從n 2處截成兩段 a 1 n 2 a n 2 1 n 例項 三 最大子段和 問題表述 n個...
最大子段和
再給頂的n個數的陣列中選出連續的若干個數,使得他們的和是最大的,即最大連續自序列和.列如.序列.1 2 3 1 6 5 9 結果 當取子串行 3,1,6,5,9 結果12 我的思路.1.最大連續子串行的開頭是在1.n之中.的最大連續和 2.求出以i,開頭的最大連續和,此時開頭已經確定了,那麼通過列舉...