考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <bits/stdc++.h> using namespace std; const int maxn = 5e5 + 50; int n, m, pre[maxn]; int head, tail, q[maxn];
int main() { cin >> n >> m; int ans = 0xc0c0c0c0; for (int i = 1; i <= n; ++i) cin >> pre[i], pre[i] += pre[i - 1]; for (int i = 0; i < n; ++i) { while (head < tail && q[head] - 1 + m < i) ++head; while (head < tail && pre[q[tail - 1]] > pre[i]) --tail; q[tail++] = i; ans = max(ans, pre[i + 1] - pre[q[head]]); } cout << ans; return 0; }
|
思路
一开始的想法肯定是前缀和,然后左端点l
和右端点r
随便选....但显然会TLE。
考虑到前缀和的公式pre[r] - pre[l - 1]
,
相同的pre[r]
时,显然pre[l - 1]
最小时就能得到m
区间长度内的极大值。
推导得到l - 1
的区间范围: \[
\\
\left( l-1 \right) \in \left[ r-m,r-1 \right] \begin{cases}
r-l+1\leqslant m\Longrightarrow r-m\leqslant l-1\\
l-1\leqslant r-1\\
\end{cases}
\]
所以用单调队列保存该区间内的极小值,用来更新r
即可