BZOJ 4385: [POI2015]Wilcze doły
显然,我们要消除长度为d的连续一段
那么可以预处理每个起点,长度为d的和
用单调队列维护消除的这段东西
再枚举右起点,考虑左起点不会左移的特性,故可以双指针。
为什么左指针不会左移?
我们考虑右指针向右移动一格,此时的区间内长度为d的最大和可以分为包含右指针指向的那一格和不包含
显然 不包含的情况就是右指针未移动的情况加上最右的那个数,显然,这时候左指针不会左移。
在考虑包含的情况,那么相当于在原来的基础上消除的长度为d的序列变短,最右边相当于没有加进来
那么此时不考虑最右边元素的情况下,删去的d个元素肯定比右指针未右移的时候是增加的
那么整体的总和是增加的,显然左指针也不会左移
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 2000010 6 int n, d, q[N]; ll p, w[N], zero[N]; 7 8 ll read() 9 { 10 ll res = 0; 11 char ch = getchar(); 12 for (; !isdigit(ch); ch = getchar()); 13 for (; isdigit(ch); ch = getchar()) res = res * 10 + ch - '0'; 14 return res; 15 } 16 17 int main() 18 { 19 while (scanf("%d%lld%d", &n, &p, &d) != EOF) 20 { 21 for (int i = 1; i <= n; ++i) 22 { 23 w[i] = read(); w[i] += w[i - 1]; 24 if (i >= d) zero[i] = w[i] - w[i - d]; 25 } 26 int pos = 1, l = 1, r = 0, ans = 0; 27 for (int i = d; i <= n; ++i) 28 { 29 while (l <= r && zero[q[r]] < zero[i]) --r; 30 q[++r] = i; 31 while (w[i] - w[pos - 1] - zero[q[l]] > p) 32 { 33 ++pos; 34 while (l <= r && q[l] - d + 1 < pos) ++l; 35 } 36 ans = max(ans, i - pos + 1); 37 } 38 printf("%d\n", ans); 39 } 40 return 0; 41 }