【k長度最大連續子序和】 最大子序和
阿新 • • 發佈:2020-09-22
傳送門
題意
長度為\(n\)的整數序列,找出一段長度不超過\(m\)的和最大的連續子序列
資料範圍
\(1\leq n \leq 3·10^{5}\)
題解
-
預處理字首和,貪心法,假如右端點\(i\)固定,找到一個左端點\(j \in [i-m,i-1]\),\(s_{j}\)要儘量的小,
-
為了使得區間和最大,\(j\)的取值,是一個區間,我們只要這個區間的最值。區間最值,就可以通過單調佇列處理。
-
如果有一個位置\(k\),\(k<j<i\).而且\(sum_{k}\geq sum_{j}\),那麼\(sum_{i}-sum_{k} \leq sum_{i} -sum_{j}\)
- 也就是說\(j\)更靠近 \(i\) ,不易超過限制\(m\),並且答案更優,那麼\(k\)是沒有用了。所以每次更新的時候先把越界的隊頭去除,剩下的顯然就是最優解
Code
#include<bits/stdc++.h> using namespace std; const int N=3e5+10; int s[N]; int n,m; int ans=-1e9; deque<int> q; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); s[i]=s[i-1]+x; } for(int i=1;i<=n;i++){ while(q.size() && i-m>q.front()) q.pop_front(); ans=max(ans,s[i]-s[q.front()]); while(q.size() && s[q.back()]>=s[i]) q.pop_back(); q.push_back(i); } printf("%d",ans); }