Min Sum Construction#12262

Min Sum Construction (Editorial)

Problem Author:

Hasan Saleh (MathModel)

Prepared by:

Hasan Saleh (MathModel)

Edited by:

Hasan Saleh (MathModel)

Solution

We are asked to construct an array of length such that 1 \le A_i \le n, \sum_{i=1}^n A_i = a and \sum_{i=1}^n \min(A_i,b) = c. The condition with the minimum is the restrictive one, so we first make this sum correct, then we fix the real sum.

Note that we never need to start from a value bigger than , because values are capped by anyway and any value gives the same contribution to the capped sum. Let B = \min(b,n) If we set

A_i = B \quad \text{for all } i=1,\dots,n,

then we currently have

\sum_{i=1}^n \min(A_i,b) = \sum_{i=1}^n B = n \cdot B,

and also

\sum_{i=1}^n A_i = n \cdot B.

Call this current capped sum \text{tot} = n \cdot B.

We want the capped sum to become exactly . Since right now every A_i \le B \le b, decreasing A_i by will decrease \min(A_i,b) by as well. So we walk from i=1 to and while \text{tot} > c we try to lower A_i. For a fixed position we cannot lower more than what is still extra, and we cannot go below , so we take

v = \min\{\, \text{tot} - c,\; A_i - 1,\; B - 1 \,\}

and do

A_i \gets A_i - v,\quad \text{tot} \gets \text{tot} - v.

After one pass the equality

\sum_{i=1}^n \min(A_i,b) = c

holds, because each unit we subtracted from some A_i \le b reduced the capped sum by exactly .

Now we check the real sum \sum A_i. If b \ge n, then B = n and \min(A_i,b) = A_i for all , so once the capped sum is we already have \sum A_i = c, and since the statement guarantees that a solution exists we must have a=c and we are done.

If b \le n, then after the decreasing phase we have the capped sum right but maybe

\sum_{i=1}^n A_i < a.

To increase the real sum without changing the capped sum we only touch positions with A_i = b. If we increase such an A_i to b + \delta with \delta \le n-b, then

\min(A_i,b) = b \quad \text{(unchanged)},

but the real sum increases by . So we scan again and whenever A_i = b and the current sum is still , we add

\delta = \min(a - \text{sum},\; n - b)

to A_i. Because the problem promises that a solution exists, we will find enough such positions to reach the exact sum . We never violate A_i \le n because we only ever raise from up to at most .

The construction is therefore:

  1. set everything to B = \min(b,n);

  2. decrease from the front to make the capped sum equal to ;

  3. if b \le n, raise only the positions currently equal to to make the real sum equal to .

Complexity is \mathcal{O}(\sum n).

for _ in range(int(input())):
    n,a,b,c=map(int,input().split())
    base=min(b,n)
    res=[base]*n
    tot=n*base
    i=0
    while i<n and tot>c:
        v=min(tot-c,res[i]-1,base-1)
        if v>0:
            res[i]-=v
            tot-=v
        i+=1
    if b<=n:
        i=0
        while i<n and tot<a:
            if res[i]==b:
                v=min(a-tot,n-b)
                if v>0:
                    res[i]+=v
                    tot+=v
            i+=1
    print(*res)