P1115 最大子段和分治

2021-10-12 20:57:19 字數 2166 閱讀 2240

p1115 最大子段和

給出乙個長度為 nn 的序列 aa,選出其中連續且非空的一段使得這段和最大。

72-

43-1

2-43

分治的解法。

首先,假定有區間[l.

.r][l.

.r],其中間位置為midmid,其最大子段為[i.

.j][i.

.j]。那麼顯然,ii和jj必定符合下列三種情況之一:

1.l \leq \leq \leq l≤i≤j≤mid

2.i \leq

3.mid < i \leq \leq mid只需要分別求出三種情況下的值,取其最大的即可。

其中,很容易求出第二種情況,即求出區間[i.

.mid]

[i..mid]與區間[mid+

1..j]

[mid+

1..j],將其相加即可。複雜度o

(n)o

(n)如何處理第一種和第三種情況呢?也不難發現,第一種情況,其實就是求區間[

1..mid][1.

.mid]中的最大值,第三種情況就是求區間[mid+

1..r]

[mid+

1..r]中的最大值。那麼,只需遞迴求出即可。

顯然,該解法的複雜度為 o

(nlogn)

o(nlogn) 通過此題是沒問題的。

附上**

`#include

int n , arr[

200200];

//arr儲存該序列

const

int minn =

-19260817

;// 定義最小值

inline

intmax

(int a ,

int b)

//自定義 max 函式(好像比stl的快一點)

intrec

(int l ,

int r )

int mid =

( l + r )

>>1;

int sum =

0, ret1 = minn , ret2 = minn;

//ret1為[l..mid]區間內包含mid的最大子段和,ret2為[mid+1..r]區間內包含(mid+1)的最大子段和

for(

int i = mid ; i >= l ; i--

)//求出[i..mid]區間最大值

sum =0;

for(

int i = mid+

1; i <= r ; i++

)//求出[mid+1..r]區間最大值

return

max(

max(

rec( l , mid )

,rec

( mid +

1, r )

), ret1 + ret2 )

;//返回可能一 可能二 可能三 中的最大值

}int

main()

printf

("%d"

,rec(1

, n));

return0;

}`

//最大子段和問題 p64 

#include

#include

using

namespace std;

intmaxsum

(int a,

int left,

int right)

;int a[

100]

;int

main

(void

)int

maxsum

(int a,

int left,

int right)

s2=0;rights=0;

for(

int j=center+

1;j<=right;j++

)//求出s2 從中間到右邊的最大和

midsum=s1+s2;

//橫跨中間的最大欄位和為s1+s2

if(midsumelse sum=midsum;

if(sum//取三者的較大者

}return sum;

}

P1115 最大子段和

給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...

P1115 最大子段和

給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...

P1115 最大子段和

給出一段序列,選出其中連續且非空的一段使得這段和最大。輸入格式 輸入檔案maxsum1.in的第一行是乙個正整數n,表示了序列的長度。第2行包含n個絕對值不大於10000的整數a i 描述了這段序列。輸出格式 輸入檔案maxsum1.out僅包括1個整數,為最大的子段和是多少。子段的最小長度為1。輸...