Luogu P3594 [POI2015]WIL-Wilcze doły(單調佇列)
阿新 • • 發佈:2021-08-24
題面:
題解:
首先我們要發現,假如右端點為\(i\) ,能到達的最遠的左端點為 \(j\) 時,那麼 右端點為 \(i+1\) 時,能到達的最遠左端點一定大於等於 \(j\) 。為什麼?假設存在這種情況,因為\(i+1\) 比 \(i\) 多了一個 \(a[i+1]\) ,那麼說明 \(i\) 的最長區間的和比 \(i+1\)小,而\(i+1\) 能到達一個更小的位置,那麼說明 \(i\) 也能到達那個位置,與假設衝突。
知道上述結論後,我們假設 \(i\) 能到達的最遠左端點為 \(last\) ,那麼我們去看 \([last,i+1]\)是否滿足條件,若不滿足,則\(last\)
如何看是否滿足呢?即區間和減去長度為\(d\)的最大區間和是否\(<\) p。 那麼就得維護最大的長度為\(d\) 的區間和。利用單調佇列即可。
程式碼:
#pragma GCC diagnostic error "-std=c++11" #include <algorithm> #include <cmath> #include <cstdio> #include <cstring> #include <ctime> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #define iss ios::sync_with_stdio(false) using namespace std; typedef unsigned long long ull; typedef long long ll; typedef pair<int, int> pii; const int mod = 1e9 + 7; const int MAXN = 2e6 + 5; const int inf = 0x3f3f3f3f; int q[MAXN]; ll a[MAXN],pre[MAXN],sum[MAXN]; int main() { int n, d; ll p; cin >> n >> p >> d; for (int i = 1; i <= n; i++) { cin >> a[i]; pre[i] = pre[i - 1] + a[i]; } int l = 0, r = 0; int ans = d; for (int i = d; i <= n;i++){ sum[i] = pre[i] - pre[i - d]; } q[l] = d; int last = 1; for (int i = d + 1; i <= n;i++) { while(l<=r&&sum[i]>sum[q[r]]) r--; while(l<=r&&q[l]-d+1<last) l++; q[++r] = i; while(pre[i]-pre[last-1]-sum[q[l]]>p) { last++; while (l <= r && q[l] - d + 1 < last) l++; } ans = max(ans, i - last + 1); } cout << ans << endl; }