NKOJ Unknow 最大子段和

2021-08-08 02:10:07 字數 1646 閱讀 6826

最大子段和

問題描述

給出乙個首尾相連的迴圈序列,從中找出連續的一段,使得該段中的數和最大。
輸入格式

第一行乙個整數 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,開頭的最大連續和,此時開頭已經確定了,那麼通過列舉...