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.
For a fixed candidate , stop thinking about exact medians. Ask whether some valid subarray can have its largest possible median at least .
Convert the array into if , and otherwise. Now a subarray is good for threshold when its transformed sum is nonnegative.
Why? A nonnegative sum means the subarray has at least as many elements as elements . That is exactly enough for the upper end of its median interval to be at least .
So the check for is: does there exist a subarray of length at least with transformed sum ? Use prefix sums and keep the minimum prefix ending at least positions before the current right endpoint.
The predicate is monotonic: if threshold works, every smaller threshold works too. Binary search , and during a successful check store the indices from , giving subarray .
The trick is to maximize the upper end of a subarray's median interval.
For a sorted subarray of length :
So the maximum median value contributed by a subarray is its upper middle value. Therefore, the answer is:
the maximum possible upper median among all subarrays of length at least .
Once we can test whether some valid subarray has upper median at least , we can binary search the answer.
Checking a fixed value
For each element, define:
Take any subarray. Let:
The transformed sum of the subarray is:
The upper median of this subarray is at least exactly when at least half of the subarray is .
That condition is:
which is the same as:
So for fixed , the whole problem becomes:
Is there a subarray of length at least whose transformed sum is nonnegative?
Nice. The median monster just turned into prefix sums. Love when Codeforces briefly stops being evil.
Prefix-sum check
Let:
and
The transformed sum of subarray is:
We need:
If we set , then this means:
For each right endpoint , we want to know whether there is some valid prefix index such that:
That is easiest if we maintain the smallest prefix value among all valid :
Then candidate works if for some :
When this happens, if the minimum prefix was at index , the witness subarray is:
Binary search
If a threshold works, then every smaller threshold also works. Lowering only changes some values into values, so subarray sums cannot get worse.
So the predicate is monotonic:
Binary search the largest working from to .
After finding the answer , run the check once more for and output its stored subarray.
Why is itself actually a median of that subarray, not just some threshold that passed? Because the check proves this subarray has upper median at least . But is the largest threshold that works globally, so no valid subarray can have upper median at least . Therefore this subarray's upper median is exactly , and is definitely inside its median interval.
Complexity
Each check is .
Binary search does checks.
Total per test case:
Across all test cases:
with , easily fine.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct CheckResult {
bool ok;
int l, r;
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, k;
cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
auto check = [&](int x) -> CheckResult {
vector<int> pref(n + 1, 0);
for (int i = 1; i <= n; i++) {
pref[i] = pref[i - 1] + (a[i] >= x ? 1 : -1);
}
int minPref = 0;
int minIdx = 0;
for (int r = k; r <= n; r++) {
int idx = r - k;
if (pref[idx] < minPref) {
minPref = pref[idx];
minIdx = idx;
}
if (pref[r] - minPref >= 0) {
return {true, minIdx + 1, r};
}
}
return {false, -1, -1};
};
int lo = 1, hi = n;
int ans = 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (check(mid).ok) {
ans = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
CheckResult res = check(ans);
cout << ans << ' ' << res.l << ' ' << res.r << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct CheckResult {
bool ok;
int l, r;
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n, k;
cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
auto check = [&](int x) -> CheckResult {
vector<int> pref(n + 1, 0);
for (int i = 1; i <= n; i++) {
pref[i] = pref[i - 1] + (a[i] >= x ? 1 : -1);
}
int minPref = 0;
int minIdx = 0;
for (int r = k; r <= n; r++) {
int idx = r - k;
if (pref[idx] < minPref) {
minPref = pref[idx];
minIdx = idx;
}
if (pref[r] - minPref >= 0) {
return {true, minIdx + 1, r};
}
}
return {false, -1, -1};
};
int lo = 1, hi = n;
int ans = 1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (check(mid).ok) {
ans = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
CheckResult res = check(ans);
cout << ans << ' ' << res.l << ' ' << res.r << '\n';
}
return 0;
}