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。輸...