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.
Think backwards: instead of subtracting from lengths , start from all zeros and add to one subarray of each length .
The length- subarray is forced: it hits every position. Then the length- subarray is the whole array except exactly one end. Then length is some interval after removing two total end positions, and so on.
If these chosen intervals are nested, each step removes either the current leftmost position or the current rightmost position. The removed position stops receiving future additions, so its final value is exactly the number of intervals that already covered it.
That means value must be at one of the two ends of the current array, then value must be at one of the two ends after removing value , then value , etc. If the next needed value is buried inside, it cannot be peeled off. Tough luck.
So use two pointers. For to , check whether or . If yes, move that pointer inward. If neither end equals , answer NO. If all values are peeled, answer YES.
We need decide whether the permutation can be created by choosing one interval of every length and subtracting from it.
A much cleaner way to look at it: reverse time.
Instead of starting with and subtracting, start with all zeros and do the operations in reverse order:
At the end, we want to get exactly .
Key Shape Observation
The length- interval is forced: it is the whole array.
Now look at the length- interval. Any subarray of length is the whole array except either the left end or the right end.
Then a length- interval has removed two positions total from the outside. If the final values are a permutation, the construction that works is exactly this peeling process: each shorter interval is obtained by removing one current endpoint.
So the intervals form a nested chain:
Each time, we delete either the current left endpoint or the current right endpoint.
Now ask: what final value does a deleted position get?
If a position is removed right after it has been included in exactly added intervals, then its final value is . Once removed, it is never touched again.
Therefore:
This gives a dead-simple test.
Algorithm
Keep two pointers:
For every value from to :
NO.If all values from to can be removed this way, answer YES.
Why This Is Correct
Suppose a valid sequence of operations exists. Reverse it. We are adding intervals of lengths . The position with final value was included only in the length- interval, so it cannot be inside the length- interval. Since the length- interval skips only one endpoint, value must be at an endpoint.
After removing that endpoint from consideration, apply the same argument to value : it must be excluded from the next smaller interval, so it must be an endpoint of the remaining segment.
Repeat this argument for every value. So any valid permutation must pass the two-pointer peeling test.
Conversely, if the peeling test passes, we can construct the intervals backwards. Start with the whole array, and whenever value is peeled from the left or right, choose the next smaller interval as the remaining segment. This creates one valid interval of each length, and each position receives exactly as many additions as its value. Reverse those additions, and we get a valid subtraction sequence.
So the two-pointer condition is both necessary and sufficient. No hidden DP, no wizardry, just peeling the array like it owes you money.
Complexity
Each element is checked and removed once.
per test case, with extra memory.
#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;
cin >> n;
vector<int> p(n);
for (int &x : p) cin >> x;
int l = 0, r = n - 1;
bool ok = true;
for (int need = 1; need <= n; need++) {
if (l <= r && p[l] == need) {
l++;
} else if (l <= r && p[r] == need) {
r--;
} else {
ok = false;
break;
}
}
cout << (ok ? "YES" : "NO") << '\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;
cin >> n;
vector<int> p(n);
for (int &x : p) cin >> x;
int l = 0, r = n - 1;
bool ok = true;
for (int need = 1; need <= n; need++) {
if (l <= r && p[l] == need) {
l++;
} else if (l <= r && p[r] == need) {
r--;
} else {
ok = false;
break;
}
}
cout << (ok ? "YES" : "NO") << '\n';
}
return 0;
}