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.
A single Increase can add any positive amount, so the actual sizes of jumps are flexible. The hard part is only deciding how many different “layers” of value you need.
Think backward from the final array. Elements with larger final values must have avoided more recent smashes than elements with smaller final values.
If the distinct target values are , then you can create them using increases: add , then later , ..., finally in the right order.
Between consecutive increases, you only need a smash if some elements should stop accumulating the earlier/larger total and restart to eventually become a smaller value.
Every distinct value needs one Increase, and every transition between distinct values needs one Smash. So if there are distinct values, the answer is .
Let the distinct values in the target array be
The answer is:
where is the number of distinct values in the array.
Why distinct values are all that matter
The positions do not matter at all. A smash operation can reset any subset of elements, so we can freely choose which elements belong to which final value group.
The only real question is: how many different final values do we need to manufacture?
If two elements both need value , they can always be treated the same way. If one needs and another needs , then they must have different histories: the element must keep some earlier increase that the element loses by being smashed.
What an element's final value means
Suppose we do several global increases. If an element is smashed at some point, everything it gained before that smash is erased. So its final value is exactly the sum of the increases that happened after its last smash.
That means different target values correspond to different suffix sums of the increase sequence.
Since every increase amount is positive, these suffix sums are strictly different as you include more increases. So to get different positive values, we need at least increase operations.
That gives the first lower bound:
But increases alone make all elements equal. To split elements into different value groups, we also need smashes.
Each smash can create one new “restart point” in time. With smashes, an element can have one of at most possible last-smash times: never smashed, after smash 1, after smash 2, and so on. Therefore, to create different final values, we need at least smashes.
So every solution needs at least
operations.
Construction
Now we show is always enough, so the lower bound is tight.
Let the distinct target values be sorted increasingly:
We build from largest value down to smallest value.
More cleanly, the increase amounts are:
After each of the first increases, we smash exactly the elements that should end with one of the smaller remaining values.
An element targeting skips the early increases that are meant only for values larger than , then keeps the remaining increases:
Telescoping saves the day. Math doing unpaid labor, classic.
So increases and smashes are enough, for a total of:
Algorithm
For each test case:
Constraints are tiny, so this is comfortably overkill in the best way.
Complexity:
per test case using a set, or basically instant for .
#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;
set<int> vals;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
vals.insert(x);
}
cout << 2 * (int)vals.size() - 1 << '\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;
set<int> vals;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
vals.insert(x);
}
cout << 2 * (int)vals.size() - 1 << '\n';
}
return 0;
}