tony4875's blog

By tony4875, history, 17 months ago, In English

Problem:

You are given an integer $$$n$$$ and a target array $$$a = [a_1, a_2, \dots, a_n]$$$. Initially, you have an array $$$b$$$ of length $$$n$$$ with all elements equal to $$$0$$$. In one operation, you select a segment $$$[l, r]$$$ ($$$1 \le l \le r \le n$$$) and positive $$$x$$$, and add $$$x$$$ to each element in that segment: $$$b[i] = b[i] + x$$$ for all $$$i$$$ in range $$$[l, r]$$$

Determine the minimum number of operations required to transform array $$$b$$$ into array $$$a$$$.

Constraints:

$$$ 1 \lt = n \lt = 10^5 $$$
$$$ 0 \lt = a_i \lt = 10^9$$$
$$$ x \gt 0 $$$

I think computing the sum of positive differences between adjacent elements $$$ans$$$ $$$+=$$$ $$$\sum_{i = 1}^n $$$ $$$max(a_i - a_{i - 1}, 0)$$$ where we set $$$a_0 = 0$$$. However, this approach only works when $$$x = 1$$$.

I appreciate any help you can provide.

  • Vote: I like it
  • +8
  • Vote: I do not like it

| Write comment?
»
17 months ago, hide # |
 
Vote: I like it +22 Vote: I do not like it

The problem boils down to:

Given a target array ( a ) and an initial array of all zeros, where you can pick any segment ([l,r]) and add any positive integer ( x ) to all elements in ([l,r]), find the minimum number of operations needed to reach ( a ).


Initially, it feels like we should just compute:

$$$ \sum_{i=1}^{n} \max(a_i - a_{i-1}, 0) \quad (a_0 = 0) $$$

because it counts the "upward movements" — but this formula only works when ( x = 1 ) per operation.

Since here we can pick any (x > 0), the task is different:
We want to cover the "histogram" defined by ( a ) with as few horizontal rectangles as possible.


Solution Idea (Monotonic Stack Approach):

  • Traverse (a) from left to right.
  • Maintain a monotonically increasing stack of previous heights.
  • At each position (i):
  • If the current height (a[i]) is less than the previous, pop until the stack is valid.
  • If the current height (a[i]) is greater than the previous, push it onto the stack and increment the answer.

Algorithm (in pseudocode):

ans = 0
stack = empty

for i = 1 to n:
    while stack not empty and stack.top > a[i]:
        stack.pop()
    if stack.empty or stack.top < a[i]:
        if a[i] > 0:
            ans += 1
            stack.push(a[i])

Why does it work? - Popping ensures that we properly close any rectangles that can’t extend further. - If (a[i]) is strictly larger than what’s on top, we need a new rectangle starting here. - Only non-zero heights are considered.


Example:

Given ( a = [1, 2, 1, 2] )

(i) (a[i]) Stack Before Action Stack After ans
1 1 [] push 1 [1] 1
2 2 [1] push 2 [1,2] 2
3 1 [1,2] pop 2, no push (top==1) [1] 2
4 2 [1] push 2 [1,2] 3

Final answer = 3 operations.


Time Complexity:

  • Each element is pushed and popped at most once → (O(n)) overall.

Summary:
If (x) is free to be any positive integer, use the monotonic stack method to count new necessary rectangle "starts."
If (x=1) is fixed, then summing positive differences $$$\max(a_i - a_{i-1}, 0)$$$ would work.


  • »
    »
    17 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Bro sounds like gpt lol

  • »
    »
    17 months ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it

    If I understood you correctly it will give the answer $$$3$$$ to the array $$$[1, 6, 5]$$$. But we can actually do it in $$$2$$$ operations:
    $$$[0, 0, 0] \rightarrow [0 + 1, 0 + 1, 0] = [1, 1, 0] \rightarrow [1, 1 + 5, 0 + 5] \rightarrow [1, 6, 5]$$$