题解 P3594 【[POI2015]WIL-Wilcze doły】

Xiefan_Guo

2019-08-11 13:09:47

Solution

首先发现答案是**单调不降的**。即选择每一个位置 $i$ 作为右端点能形成的最长区间的**左端点是单调不降的**。将 $i-1$ 这个位置作为结尾形成的最长区间的左端点不可能比 $i$ 作为结尾形成的最长区间的左端点更靠右 $sum[]$ 为数列前缀和。 $start$ 为起始左端点。如果 $sum[i]-sum[start-1]$ 即这段**区间的和**减去这个区间内所有**长度为 $d$ 的区间和的最大值**超过 $p$ ,那么我们就让 $start++$ ,直到满足条件为止。 ```c #include<bits/stdc++.h> using namespace std; const int maxn = 2000005; int n, d, l, r, start, ans; int que[maxn]; long long p, a[maxn], sum[maxn], ad[maxn]; int solve() { l = r = 1; start = 1; for(int i = d; i <= n; i++){ ad[i] = sum[i] - sum[i - d]; } int ret = d; que[r++] = d; for(int i = d + 1; i <= n; i++){ while(l < r && ad[i] > ad[que[r - 1]]) r--; que[r++] = i; while(l < r && sum[i] - sum[start - 1] - ad[que[l]] > p){ start++; while(l < r && que[l] - d + 1 < start) l++; } ret = max(ret, i - start + 1); } return ret; } int main() { scanf("%d%lld%d", &n, &p, &d); for(int i = 1; i <= n; i++){ scanf("%lld", &a[i]); sum[i] = sum[i - 1] + a[i]; } ans = solve(); printf("%d\n", ans); return 0; } ```