Luogu 3594 [POI2015]WIL-Wilcze doły

时间:2021-03-29 12:26:26

简单题。

考虑没有修改数字的条件的限制,我们直接用双指针扫描就可以计算出答案了。

然后考虑加入修改数字的条件,只要用单调队列维护出当前两个指针表示的区间中长度为$d$的一段区间的最大值,用总和减掉这个最大值更新答案即可。

时间复杂度$O(n)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 2e6 + ; int n, d, q[N];
ll lim, a[N], sum[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} int main() {
read(n), read(lim), read(d);
for(int i = ; i <= n; i++) {
read(a[i]);
sum[i] = sum[i - ] + a[i];
} int l = , r = , last = , ans = d;
for(int i = d; i <= n; i++) {
for(; l <= r && sum[i] - sum[i - d] > sum[q[r]] - sum[q[r] - d]; --r);
q[++r] = i;
for(; l <= r && q[l] - d < last; ++l);
for(; l <= r && sum[i] - sum[last] - sum[q[l]] + sum[q[l] - d] > lim; ) {
++last;
for(; l <= r && q[l] - d < last; ++l);
}
chkMax(ans, i - last);
} printf("%d\n", ans);
return ;
}