1. 程式人生 > >BZOJ 4385: [POI2015]Wilcze doły

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 }
View Code