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
then we currently have
and also
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
and do
After one pass the equality
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
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
but the real sum increases by . So we scan again and whenever A_i = b and the current sum is still , we add
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:
set everything to B = \min(b,n);
decrease from the front to make the capped sum equal to ;
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)