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

 

posted @ 2018-11-21 23:01  Dup4  阅读(122)  评论(0编辑  收藏  举报