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.
Stop thinking about the values inside every range directly. Since is a permutation, each value has exactly one position. A range has MEX at least iff it contains the positions of every value .
For each prefix of values , only two numbers matter: the minimum and maximum positions among those values. Call them and . Then a query range has MEX at least exactly when and .
So the answer is the largest such that some given range contains the segment . This dodges computing MEX per query entirely. Nice little jailbreak.
To test whether any query contains a segment , sort/query the ranges by left endpoint. For each possible left boundary, keep the maximum right endpoint among all ranges starting at or before it.
Build an array maximum among all given ranges with . Then is contained in some range iff . Scan while updating , and also remember that answer is at least .
We are given the hidden permutation directly in the hacked version, so this becomes a clean offline interval problem.
The obvious move is to compute the MEX of every query range. That works conceptually, but it is way too chunky if you do it from scratch: can be huge. Instead, flip the question around.
A range has MEX at least iff it contains all values
Because is a permutation, every value has one position. Let be the index where value appears.
For a fixed , the range must contain every position
That is equivalent to containing just their span:
So a query range has MEX at least iff
That is the whole trick. No need to inspect actual range contents. The values already told us their positions. Very polite of them.
From Exact MEX To A Threshold
The answer asks for the maximum exact MEX among the given ranges. But we can instead maximize the threshold condition “MEX is at least ”.
If some range has MEX , then it has MEX at least every . Conversely, if some range has MEX at least , then the maximum MEX is at least .
Therefore the answer is:
For , this is always true, because every range has MEX at least . So initialize the answer to .
For , we scan values in increasing order and maintain the span:
Checking Containment Fast
Now we need to answer this repeatedly:
Given a segment , does there exist a query range with
For every left boundary , store the best right endpoint of any range starting exactly at :
Then prefix-max it:
Now means:
among all query ranges with left endpoint at most , what is the farthest right endpoint?
So a segment is contained in some query range iff
That is an check.
Algorithm
For each test case:
startBest[l] = max(startBest[l], r).startBest so startBest[i] becomes the maximum right endpoint among ranges with left endpoint .ans = 0.pos[value];startBest[L] >= R, then some range has MEX at least value + 1, so update ans.ans.Why This Is Correct
We prove the algorithm returns the maximum MEX among all given ranges.
First, for any integer , a range has MEX at least iff it contains every value from to . Since is a permutation, those values appear at positions . A range contains all those positions iff it contains their minimum and maximum position span . Thus a query range has MEX at least iff it contains .
Second, after prefix-maxing, startBest[L] is the largest right endpoint among all query ranges whose left endpoint is at most . Therefore startBest[L] >= R holds iff there exists a query range with and , which is exactly the condition that the query range contains .
The scan considers every possible threshold , maintaining exactly xx$. Since the maximum exact MEX equals the largest achievable threshold, the final answer is correct.
Complexity
Building positions takes . Reading ranges and building prefix maxima takes . Scanning all possible MEX thresholds takes .
So each test case runs in
with memory. That easily fits. No drama, no segment tree cosplay needed.
#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;
while (T--) {
int n, q;
cin >> n >> q;
vector<int> pos(n);
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
pos[x] = i;
}
vector<int> best(n + 1, 0);
for (int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
best[l] = max(best[l], r);
}
for (int i = 1; i <= n; i++) {
best[i] = max(best[i], best[i - 1]);
}
int ans = 0;
int L = n + 1, R = 0;
for (int value = 0; value < n; value++) {
L = min(L, pos[value]);
R = max(R, pos[value]);
if (best[L] >= R) ans = value + 1;
}
cout << ans << '\n';
}
return 0;
}#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;
while (T--) {
int n, q;
cin >> n >> q;
vector<int> pos(n);
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
pos[x] = i;
}
vector<int> best(n + 1, 0);
for (int i = 0; i < q; i++) {
int l, r;
cin >> l >> r;
best[l] = max(best[l], r);
}
for (int i = 1; i <= n; i++) {
best[i] = max(best[i], best[i - 1]);
}
int ans = 0;
int L = n + 1, R = 0;
for (int value = 0; value < n; value++) {
L = min(L, pos[value]);
R = max(R, pos[value]);
if (best[L] >= R) ans = value + 1;
}
cout << ans << '\n';
}
return 0;
}