Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
You are looking for a contiguous time period, so this is a subarray problem. The condition only depends on the window's minimum and maximum height: That should scream “sliding window” at least a little.
Notice the monotonicity: if a window is valid, then every subwindow inside it is also valid. So for each fixed right endpoint , there is a smallest left endpoint such that is valid. That’s exactly the kind of crap two pointers loves.
The annoying part is checking the window quickly while it moves. You need to support:
A multiset gives , but there’s a cleaner weapon: two monotonic deques.
Maintain:
When you extend to , push into both deques while preserving monotonicity. While move right and discard indices that fall out of the window.
After shrinking, the current window is the longest valid window ending at . So its length is Track the global best length:
That’s it. One pass, two deques, no black magic:
We need a contiguous segment such that
and among all such segments we want the maximum length , then all segments achieving that length.
So yes, this is a sliding-window problem. The only real question is: how do we maintain window minimum and maximum fast enough?
Suppose a window is valid. Then every subwindow inside it is also valid, because removing elements cannot increase the range
That means for each fixed right endpoint , there is a smallest left endpoint such that is valid. If we increase , this never moves left. Classic two-pointers territory.
So the plan is:
The last sentence is the key aha.
If you use a multiset, you get and it passes. But we can do better and cleaner with two deques:
mx: indices of elements in decreasing height order, so the front is the maximum.mn: indices of elements in increasing height order, so the front is the minimum.When adding index :
mx.back() has height , pop it, then push ;mn.back() has height , pop it, then push .When moving right:
mx.front() == l, pop it;mn.front() == l, pop it.Then the current window range is simply
That’s amortized per operation, because each index enters and leaves each deque once. Beautiful, brutal, effective.
After we finish shrinking for a fixed , the window is valid and minimal in . Therefore it is the longest valid segment ending at .
Its length is
Now suppose some optimal answer is a segment of maximum length best. Since is the longest valid segment ending at , we have
But best is the global maximum possible length, so actually equality must hold, hence .
So every optimal segment appears exactly as the current window for its right endpoint. No need to enumerate shorter valid subwindows or do any weird nonsense.
Initialize:
mx, mnbest = 0For each :
best = len, clear the answer list, and store .We print 1-based indices because Codeforces would absolutely love to WA you for that.
We maintain the invariant that after processing each :
mx.front() is the index of the maximum in the window,mn.front() is the index of the minimum in the window,Thus is the longest valid segment ending at .
Taking the maximum over all gives the global optimum. Storing all windows whose length equals that optimum gives exactly the required periods.
No holes, no handwaving, no sacrificial goats.
Each index is pushed and popped from each deque at most once.
So the total complexity is
with memory
for the answer list in the worst case (plus input, deques in total).
That is comfortably within the limits.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() { setIO();
int n, k;
cin >> n >> k;
vector<int> h(n);
for (int i = 0; i < n; ++i) cin >> h[i];
deque<int> mx, mn;
int l = 0;
int best = 0;
vector<pair<int,int>> ans;
for (int r = 0; r < n; ++r) {
while (!mx.empty() && h[mx.back()] <= h[r]) mx.pop_back();
mx.push_back(r);
while (!mn.empty() && h[mn.back()] >= h[r]) mn.pop_back();
mn.push_back(r);
while (!mx.empty() && !mn.empty() && h[mx.front()] - h[mn.front()] > k) {
if (mx.front() == l) mx.pop_front();
if (mn.front() == l) mn.pop_front();
++l;
}
int len = r - l + 1;
if (len > best) {
best = len;
ans.clear();
ans.push_back({l + 1, r + 1});
} else if (len == best) {
ans.push_back({l + 1, r + 1});
}
}
cout << best << ' ' << ans.size() << '\n';
for (auto [L, R] : ans) {
cout << L << ' ' << R << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() { setIO();
int n, k;
cin >> n >> k;
vector<int> h(n);
for (int i = 0; i < n; ++i) cin >> h[i];
deque<int> mx, mn;
int l = 0;
int best = 0;
vector<pair<int,int>> ans;
for (int r = 0; r < n; ++r) {
while (!mx.empty() && h[mx.back()] <= h[r]) mx.pop_back();
mx.push_back(r);
while (!mn.empty() && h[mn.back()] >= h[r]) mn.pop_back();
mn.push_back(r);
while (!mx.empty() && !mn.empty() && h[mx.front()] - h[mn.front()] > k) {
if (mx.front() == l) mx.pop_front();
if (mn.front() == l) mn.pop_front();
++l;
}
int len = r - l + 1;
if (len > best) {
best = len;
ans.clear();
ans.push_back({l + 1, r + 1});
} else if (len == best) {
ans.push_back({l + 1, r + 1});
}
}
cout << best << ' ' << ans.size() << '\n';
for (auto [L, R] : ans) {
cout << L << ' ' << R << '\n';
}
}