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.
Do not try to compute medians of subarrays directly. For a guessed median threshold , convert each element into if it is at least , otherwise . Then a subarray has median at least exactly when its transformed sum is nonnegative.
Now the expression becomes: choose a threshold , find any subarray with transformed sum , and make its minimum as small as possible. Then it contributes .
Since this is the easy version, values are only up to . That means we can enumerate the minimum value and the median threshold without touching scary value-compression wizardry.
For fixed , a valid subarray must contain no value below , contain at least one value equal to , and have transformed sum . Values below split the array into independent segments.
Inside one segment where all values are at least , scan prefix sums of . To force the subarray to contain an element equal to , keep the minimum prefix sum seen before or at positions where an has appeared. If current prefix minus that minimum is nonnegative, this is achievable.
We need maximize
The annoying part is the median. The minimum is chill: if we decide the minimum is , then the subarray must contain at least one and no value smaller than .
The median has a standard trick.
For a candidate value , define
For a subarray of length , its upper median is at least iff at least half of its elements are . With this problem's median definition, that is exactly:
For even length, a tie is enough. For odd length, the sum cannot be , so still means positive. Nice little parity freebie.
So the problem becomes:
For some minimum and median threshold , does there exist a subarray such that:
If yes, then answer can be at least .
Because this is the easy version, . So we can simply try all and . That's only pairs. The only thing we need is an check per pair that is not stupidly complicated.
Checking one pair
Elements smaller than are forbidden, so they split the array into segments. We scan left to right and reset whenever .
Inside a valid segment, define prefix sum over the transformed values:
We need a subarray ending at the current position with sum and containing at least one .
Suppose the subarray is . Its sum is
We want this to be nonnegative, so we want a small earlier prefix . But there is also the “must contain an ” condition.
When we see an element , then any future subarray that starts before or at this position and ends later will contain an . So before adding this element, we take the best prefix available so far and mark it as eligible.
More concretely while scanning a segment:
pref = current prefix sum,bestPrefix = minimum prefix sum seen so far in this segment,bestWithM = minimum prefix sum among starts that would make the chosen subarray contain an .At each position:
pref.That is the whole check. No median sorting, no cursed subarray enumeration.
Complexity
There are at most possible values for and possible values for . Each check is .
So the total complexity is
which is totally fine for the easy version because the value cap is tiny and the scan is extremely simple. Memory usage is besides the input array.
One small optimization: only try , since cannot improve the answer. The answer is always at least from any length- subarray.
#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 T;
cin >> T;
const int INF = 1e9;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
int mx = 0;
for (int &x : a) {
cin >> x;
mx = max(mx, x);
}
int ans = 0;
for (int mn = 1; mn <= mx; mn++) {
for (int med = mn + ans + 1; med <= mx; med++) {
int pref = 0;
int bestPrefix = 0;
int bestWithMin = INF;
bool ok = false;
for (int x : a) {
if (x < mn) {
pref = 0;
bestPrefix = 0;
bestWithMin = INF;
continue;
}
if (x == mn) {
bestWithMin = min(bestWithMin, bestPrefix);
}
pref += (x >= med ? 1 : -1);
if (bestWithMin != INF && pref - bestWithMin >= 0) {
ok = true;
break;
}
bestPrefix = min(bestPrefix, pref);
}
if (ok) ans = max(ans, med - mn);
}
}
cout << ans << '\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 T;
cin >> T;
const int INF = 1e9;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
int mx = 0;
for (int &x : a) {
cin >> x;
mx = max(mx, x);
}
int ans = 0;
for (int mn = 1; mn <= mx; mn++) {
for (int med = mn + ans + 1; med <= mx; med++) {
int pref = 0;
int bestPrefix = 0;
int bestWithMin = INF;
bool ok = false;
for (int x : a) {
if (x < mn) {
pref = 0;
bestPrefix = 0;
bestWithMin = INF;
continue;
}
if (x == mn) {
bestWithMin = min(bestWithMin, bestPrefix);
}
pref += (x >= med ? 1 : -1);
if (bestWithMin != INF && pref - bestWithMin >= 0) {
ok = true;
break;
}
bestPrefix = min(bestPrefix, pref);
}
if (ok) ans = max(ans, med - mn);
}
}
cout << ans << '\n';
}
}