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.
Try looking at the process row by row (height by height), not column by column. After gravity points right, cubes in the same row just slide right while keeping their left-to-right order. So the real question is: in one fixed row, which cubes can possibly stay in the same column?
For a row with occupied columns , after sliding right those cubes end up at columns . A cube stays put only if its original position already matches its final one. That means the stationary cubes in a row are exactly the ones forming a consecutive occupied suffix on the right. No suffix, no mercy.
Convert that row observation back to columns. A cube in column at height stays iff every column from to has height at least . So column contributes exactly stationary cubes, where is the suffix minimum. Therefore, without any operation,
Now suppose you decrease by . Which suffix minima change? Only with , and each can drop by at most . In fact, Since , you always have , so decreases iff . Thatβs the whole trick.
Let be the suffix minima. If you decrease position , the total number of cubes drops by , and the number of stationary cubes drops by So the number of moved cubes changes by Hence the answer is Compute in one backward pass, then scan left-to-right maintaining frequencies of seen suffix minima. If , then is just the current frequency of value .
If you stare at the columns too hard, the problem starts looking cursed. Donβt do that.
Fix a height . Look only at cubes on that row. Suppose they occupy columns After gravity points right, these cubes slide as far right as possible, preserving order, so they end up at
So when does a cube on this row not move? Exactly when its original position already equals its final one. That means the stationary cubes on a row are precisely the cubes in the rightmost consecutive occupied suffix of that row.
Example: if a row looks like then after shifting right it becomes Only the last cubes were already forming the right suffix, so only those stay.
Now translate that row condition back into columns.
Take a cube at column and height . It stays in the same column iff in row , columns are all occupied. In other words, That is equivalent to
So column contributes exactly stationary cubes.
Therefore the total number of stationary cubes is where is the suffix minimum.
Since the total number of cubes is the number of moved cubes without using the operation is
Thatβs already half the problem done. The other half is: what happens if we decrease one by ?
Suppose we decrease to .
For any , the suffix does not include position , so stays unchanged.
For any , the new suffix minimum is Because , we always have So the only way changes is when in which case it drops by exactly .
Thatβs the key insight. No DP wizardry, no black magic. Just suffix minima being brutally simple.
So if we decrease position , the total stationary count decreases by At the same time, total cubes decrease by exactly .
Hence the moved count changes by
So the final answer is
We need
Now notice that is the suffix minimum array, so it is nondecreasing from left to right:
If , then actually . Why? Because if , then there is a smaller value somewhere to the right of , so decreasing does nothing to any suffix minimum.
If , then is just the number of times value has appeared in the prefix .
So we can scan from left to right, maintain a frequency table of seen suffix minima, and for each position :
Take the maximum candidate gain, or if doing nothing is better.
For each test case:
freq[value] = how many times this suffix minimum value has appeared so far.freq[m_j],We already proved:
Therefore decreasing decreases the stationary total by exactly while decreasing the total cube count by . So the number of moved cubes increases by . Maximizing over all (and comparing with doing nothing) gives the formula above.
No gaps, no handwaving, no "trust me bro".
Each test case is processed in linear time:
So total complexity is per test case, and overall which fits comfortably under the constraints.
Memory usage is also linear:
Pretty damn efficient for something that initially looks like it wants a physics engine.
#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> a(n + 1), suf(n + 2), freq(n + 1, 0);
ll sumA = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
sumA += a[i];
}
suf[n] = a[n];
for (int i = n - 1; i >= 1; --i) {
suf[i] = min(a[i], suf[i + 1]);
}
ll stationary = 0;
for (int i = 1; i <= n; ++i) stationary += suf[i];
ll baseMoved = sumA - stationary;
ll bestGain = 0;
for (int i = 1; i <= n; ++i) {
++freq[suf[i]];
if (a[i] == suf[i]) {
bestGain = max(bestGain, (ll)freq[a[i]] - 1);
}
}
cout << baseMoved + bestGain << '\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;
while (t--) {
int n;
cin >> n;
vector<int> a(n + 1), suf(n + 2), freq(n + 1, 0);
ll sumA = 0;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
sumA += a[i];
}
suf[n] = a[n];
for (int i = n - 1; i >= 1; --i) {
suf[i] = min(a[i], suf[i + 1]);
}
ll stationary = 0;
for (int i = 1; i <= n; ++i) stationary += suf[i];
ll baseMoved = sumA - stationary;
ll bestGain = 0;
for (int i = 1; i <= n; ++i) {
++freq[suf[i]];
if (a[i] == suf[i]) {
bestGain = max(bestGain, (ll)freq[a[i]] - 1);
}
}
cout << baseMoved + bestGain << '\n';
}
}