字首和+單調佇列題目描述
輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。
例如 1,-3,5,1,-2,3
當m=4時,s=5+1-2+3=7
當m=2或m=3時,s=5+1=6
輸入格式
第一行兩個數n,m
第二行有n個數,要求在n個數找到最大子序和
輸出格式
乙個數,數出他們的最大子序和
輸入樣例 #1
6 41 -3 5 1 -2 3
輸出樣例 #1
7
問題區間[i,
j]
[i,j]
[i,j
] 的中子序和可以根據字首和得出:sum
=arr
[j]−
arr[
i−1]
sum=arr[j]-arr[i-1]
sum=ar
r[j]
−arr
[i−1
] 所以將問題轉化為尋找兩個位置 i,j
i,ji,
j 使得區間[i,
j]
[i,j]
[i,j
] 內子序和最大,並且j−i
≤m
j-i \le m
j−i≤m
我們通過列舉右端點 jj
j得到答案,當 jj
j固定時,問題又轉化為尋找使 arr
[i]
arr[i]
arr[i]
最小的 ii
i,並且 i∈[
j−m,
j−1]
i \in [j-m,j-1]
i∈[j−m
,j−1
]可以用單調佇列 q
qq 來儲存這些 位置 ,思想是在佇列中及時排除一定不是最優解的元素
我們定義隊首為 l
ll ,隊尾為 r
rr ,對右端點 i
ii 操作(先進先出 l
ll 先進,r
rr 先出),隊首元素中儲存著最優位置
1、判斷隊首元素 p[l
]p[l]
p[l]
與 ii
i 的距離是否大於 m,大於將隊首元素出隊
2、更新答案 ans
=max
(ans
,arr
[i]−
arr[
q[l]
])
ans = max(ans, arr[i] - arr[q[l]])
ans=ma
x(an
s,ar
r[i]
−arr
[q[l
]])
3、判斷當前元素與隊尾元素的字首和大小,此時 i
ii 是一定比 q[r
]q[r]
q[r]
大的,因為後進的嘛,如果 arr
[q[r
]]
>=a
rr[i
]arr[q[r]]>=arr[i]
arr[q[
r]]>=a
rr[i
] 說明 arr
[q[r
]]
arr[q[r]]
arr[q[
r]] 已經不可能是最優解了,輪不到arr
[q[r
]]
arr[q[r]]
arr[q[
r]] 做貢獻了,將其出隊
在本題的單調佇列中元素是遞增的 q[l
]
r]
q[l]q[
l]r]
,當位置 q[l
]q[l]
q[l]
因為超過m而不合法時,下乙個最小的字首和出來做貢獻,以此類推
#include
#include
#include
using namespace std;
static
const
auto io_sync_off =
()()
;const
int maxn =
300005
;int arr[maxn]
, q[maxn]
;int
main()
q[1]
=0;int l =
1, r =
1, ans =0;
for(
int i =
1; i <= n;
++i)
cout << ans;
return0;
}
CH1201 最大子串行和
一道關於單調佇列的模板題。題目要求求一段區間,使得這一段區間的和最大且區間長度不超過m。我們顯然想到了先求出這個序列的字首和sum,這樣我們就能用o 1 的時間查詢任意乙個子串行的和。現在,我們列舉區間的右端點,對於每乙個右端點i,我們要找到乙個左端點j,使得sum j 最小而且i j m.因此,我...
TYVJ 1305 最大子序和 烽火傳遞
描述 輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。例如 1,3,5,1,2,3 當m 4時,s 5 1 2 3 7 當m 2或m 3時,s 5 1 6 第一行兩個數n,m 第二行有n個數,要求在n個數找到最大子序和 乙個數,數出他們的最大子序和 6 4 1 3...
tyvj1305 最大子序和(單調佇列
時間限制 記憶體限制 評測方式 題目 1000ms 131072kib 標準比較器 local 輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。例如 1,3,5,1,2,3 當m 4時,s 5 1 2 3 7 當m 2或m 3時,s 5 1 6 第一行兩個數n,m...