CF 1486A - Shifting Stacks
We are given a sequence of stacks, each with some number of blocks. The task is to decide if we can redistribute blocks, moving them only to the right, to make the stack heights strictly increasing.
Rating: 900
Tags: greedy, implementation
Solve time: 1m 53s
Verified: yes
Solution
Problem Understanding
We are given a sequence of stacks, each with some number of blocks. The task is to decide if we can redistribute blocks, moving them only to the right, to make the stack heights strictly increasing. Each move consists of taking one block from stack $i$ and placing it onto stack $i+1$. We do not remove or discard stacks; even empty stacks remain in place.
The input consists of multiple test cases. Each test case gives the number of stacks $n$ and a list of heights. The output is YES if we can achieve a strictly increasing sequence and NO otherwise.
The constraints are modest: $n \le 100$ and the sum of all $n$ across test cases is at most $10^4$. This allows any algorithm that is roughly $O(n)$ per test case, since $10^4$ total operations is feasible under a 1-second time limit. However, a naive brute-force that simulates moving single blocks repeatedly could take up to $10^9$ steps if stack heights are near the upper bound, which is far too slow.
Edge cases that can trip up a naive solution include stacks with zero height, all stacks equal, or very large numbers that require careful accumulation of excess blocks. For example, an input like [0, 0, 1] cannot be made strictly increasing because the first two stacks start at zero and we cannot move blocks left. Similarly [1000000000, 1000000000, 1000000000] can be adjusted by moving excess blocks gradually to the right to form [0, 1, 2] plus offsets, demonstrating that the solution must track cumulative surplus, not just individual pair differences.
Approaches
The brute-force approach would simulate every possible move, taking one block at a time and shifting it right until no more moves can be made. This is correct in principle, because eventually all excess blocks would be distributed to satisfy the strictly increasing condition if possible. The problem is that a single test case with stacks of height $10^9$ would require billions of moves, which is infeasible.
The key insight is to notice that each stack can contribute a certain "excess" to the next stack. If the first stack has more than zero blocks, it can give as many as $h_0$ blocks to the next stack. More generally, the $i$-th stack must be able to supply enough blocks to ensure that all previous positions can reach the strictly increasing requirement. Formally, after distributing excess blocks from left to right, the $i$-th stack must have at least $i$ blocks in total. This transforms the problem into a simple linear scan, keeping track of the cumulative surplus and checking if each stack can satisfy its required minimum.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O(sum of all heights) | O(n) | Too slow for large heights |
| Optimal | O(n) per test case | O(1) extra | Accepted |
Algorithm Walkthrough
- Read the number of test cases $t$. For each test case, read $n$ and the heights array $h$.
- Initialize a variable
surplusto zero. This will track the number of blocks we can carry over to the next stack. - Iterate through the stacks from left to right using an index $i$ (0-based).
- For each stack, add the current height $h[i]$ to
surplus. This represents all blocks available for use, including what has been carried over. - Check if
surplusis at least $i$, the minimum number of blocks needed so far to make the sequence strictly increasing. Ifsurplus < i, output NO and stop for this test case. - Otherwise, subtract $i$ from
surplusto account for the blocks used to reach the strictly increasing requirement at this position. Continue to the next stack. - If all stacks satisfy the requirement, output YES.
The reason this works is that surplus tracks the total number of blocks we can shift to the right. The strictly increasing requirement at index $i$ is that there must be at least $i$ blocks accumulated by that point, because the minimum strictly increasing sequence for index $i$ is [0, 1, 2, ..., n-1]. If we can meet this requirement at every step, the final distribution can always be realized by shifting blocks right, making the sequence strictly increasing.
Python Solution
import sys
input = sys.stdin.readline
def solve():
t = int(input())
for _ in range(t):
n = int(input())
h = list(map(int, input().split()))
surplus = 0
possible = True
for i in range(n):
surplus += h[i]
if surplus < i:
possible = False
break
surplus -= i
print("YES" if possible else "NO")
if __name__ == "__main__":
solve()
The solution reads input efficiently using sys.stdin.readline. surplus accumulates available blocks. At each stack, we ensure there are enough blocks to satisfy the strictly increasing condition. If not, we terminate early to avoid unnecessary computation. Subtracting i from surplus accounts for using blocks to meet the minimum required at that position. Off-by-one errors are avoided by using 0-based indexing consistently.
Worked Examples
Consider the input [3, 4, 4, 4]:
| i | h[i] | surplus before check | required i | surplus after check |
|---|---|---|---|---|
| 0 | 4 | 0+4=4 | 0 | 4-0=4 |
| 1 | 4 | 4+4=8 | 1 | 8-1=7 |
| 2 | 4 | 7+4=11 | 2 | 11-2=9 |
All stacks satisfy the requirement, output is YES.
Input [0, 1, 0]:
| i | h[i] | surplus before check | required i | surplus after check |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 0+1=1 | 1 | 1-1=0 |
| 2 | 0 | 0+0=0 | 2 | 0<2 → NO |
This shows the algorithm correctly detects insufficient blocks.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) per test case | Each stack is processed exactly once with simple arithmetic |
| Space | O(1) extra | Only a few integers are used; input array dominates memory, which is required anyway |
Given the sum of $n \le 10^4$ over all test cases, this solution runs comfortably within the 1-second limit.
Test Cases
import sys, io
def run(inp: str) -> str:
sys.stdin = io.StringIO(inp)
output = io.StringIO()
sys.stdout = output
solve()
sys.stdout = sys.__stdout__
return output.getvalue().strip()
# provided samples
assert run("6\n2\n1 2\n2\n1 0\n3\n4 4 4\n2\n0 0\n3\n0 1 0\n4\n1000000000 1000000000 1000000000 1000000000\n") == \
"YES\nYES\nYES\nNO\nNO\nYES"
# custom cases
assert run("1\n1\n0\n") == "YES", "single stack zero"
assert run("1\n1\n100\n") == "YES", "single stack non-zero"
assert run("1\n3\n0 0 0\n") == "NO", "all zeros"
assert run("1\n3\n0 1 2\n") == "YES", "already strictly increasing"
assert run("1\n3\n2 2 2\n") == "YES", "equal heights that can be adjusted"
| Test input | Expected output | What it validates |
|---|---|---|
1\n1\n0\n |
YES | Single stack zero height |
1\n1\n100\n |
YES | Single stack non-zero height |
1\n3\n0 0 0\n |
NO | All zeros, cannot increase |
1\n3\n0 1 2\n |
YES | Already strictly increasing |
1\n3\n2 2 2\n |
YES | Equal heights, can redistribute |
Edge Cases
For [0, 0, 1], the algorithm computes surplus=0 at index 0, surplus=0 at index 1, and surplus=1 at index 2. The required minimum is 2 at index 2. Since surplus < i, it outputs NO. This correctly handles the case where the first two stacks are empty and there is no way to shift blocks left.
For [1000000000, 1000000000, 1000000000], surplus grows rapidly: 1e9 → 2e9-1 → 3e9-3. At each step, surplus >= i,