BZOJ 4385: [POI2015]Wilcze doły
阿新 • • 發佈:2018-11-21
顯然,我們要消除長度為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 * 10View Code+ 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 }