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.
Every operation deletes exactly one element. So stop thinking about the deletion order first; minimizing operations is the same as maximizing how many elements survive.
The value is immortal: it can only be removed by being next to a larger local maximum, and no larger value exists.
Since survives, it cannot be internal in the final cool array. If it had survivors on both sides, it would be a peak. So the rest of the answer must live on only one side of .
Repeat that idea recursively: inside any remaining interval, its maximum is the important splitter, and survivors cannot branch to both sides of it. This is the max Cartesian tree trying very hard to be noticed.
In the max Cartesian tree, the survivors can be one root-to-leaf chain. Therefore the maximum final length is the tree height, and the answer is .
Research checked: official Codeforces tutorial, CF Step hints and code, plus maspy's note with an AC submission link. They all point to the same max-Cartesian-tree height formula; the proof below is written from the supplied statement.
Turn operations into survivors
Each operation removes exactly one element. If the final array has elements, the number of operations is , so we want the largest possible set of survivors.
The value can never be removed. A removed element must be adjacent to a chosen local maximum that is larger than it, and nothing is larger than . Also, in the final cool array, cannot have survivors on both sides, because then it would be an internal local maximum. So the final survivors are forced into a very narrow shape; this is not a random LIS/LDS problem, despite the temptation.
Cartesian tree view
Build the max Cartesian tree of the permutation:
Now prove the key claim: the final survivors must form a single ancestor chain in this tree.
Assume two incomparable positions both survive. Let . Then is the maximum position in the interval , and and lie on opposite sides of .
If also survives, then in the final array there is some surviving element to the left of and some surviving element to the right of . Both are smaller than , so becomes an internal peak. That violates coolness.
If is deleted, it must be deleted while adjacent to a larger value. But every value larger than lies outside . A larger value on the left can never become adjacent to because survivor stays between them; a larger value on the right is blocked by survivor . So cannot be deleted either. Contradiction.
Therefore no two incomparable nodes can both survive. Since the root always survives, all survivors lie on one root-to-leaf chain. Hence any valid final array has length at most the height of the max Cartesian tree, where height counts vertices.
Why the bound is achievable
Take a longest root-to-leaf path in the Cartesian tree. We can keep exactly those nodes.
Process the path from the root downward. At a path node , if it has a child subtree not used by , repeatedly choose as the local maximum and delete the neighbor on that off-path side. This is legal because is larger than every value in its child subtrees, and the path continues through the other child whenever an off-path child exists. Once the off-path side is gone, move to the next node of .
After deleting all off-path subtrees, only the path remains. The root and leaf are endpoints. Every other remaining node has its parent adjacent on one side, and the parent is larger, so it cannot be a peak. Thus the path is cool.
So the optimal final length is exactly
where is the height of node in the max Cartesian tree. The answer is
Implementation
Build the max Cartesian tree in using a monotone decreasing stack of indices. For each index :
Then compute heights without recursion. Since every child has a smaller value than its parent, process values . At ,
Missing children have height .
Edge cases are automatic: monotone arrays produce a chain of height and answer ; if is at an endpoint, the root just has one side. Total complexity is per test case and memory, so over all tests it is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void solve() {
int n;
cin >> n;
vector<int> a(n + 1), pos(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
pos[a[i]] = i;
}
vector<int> leftChild(n + 1, 0), rightChild(n + 1, 0), st;
st.reserve(n);
for (int i = 1; i <= n; i++) {
int last = 0;
while (!st.empty() && a[st.back()] < a[i]) {
last = st.back();
st.pop_back();
}
if (last != 0) leftChild[i] = last;
if (!st.empty()) rightChild[st.back()] = i;
st.push_back(i);
}
vector<int> height(n + 1, 0);
for (int v = 1; v <= n; v++) {
int u = pos[v];
height[u] = 1 + max(height[leftChild[u]], height[rightChild[u]]);
}
cout << n - height[pos[n]] << '\n';
}
int main() {
setIO();
int t;
cin >> t;
while (t--) solve();
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void solve() {
int n;
cin >> n;
vector<int> a(n + 1), pos(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
pos[a[i]] = i;
}
vector<int> leftChild(n + 1, 0), rightChild(n + 1, 0), st;
st.reserve(n);
for (int i = 1; i <= n; i++) {
int last = 0;
while (!st.empty() && a[st.back()] < a[i]) {
last = st.back();
st.pop_back();
}
if (last != 0) leftChild[i] = last;
if (!st.empty()) rightChild[st.back()] = i;
st.push_back(i);
}
vector<int> height(n + 1, 0);
for (int v = 1; v <= n; v++) {
int u = pos[v];
height[u] = 1 + max(height[leftChild[u]], height[rightChild[u]]);
}
cout << n - height[pos[n]] << '\n';
}
int main() {
setIO();
int t;
cin >> t;
while (t--) solve();
}