<p>You are given an integer array <code>nums</code> and an integer <code>k</code>. Append <code>k</code> <strong>unique positive</strong> integers that do <strong>not</strong> appear in <code>nums</code> to <code>nums</code> such that the resulting total sum is <strong>minimum</strong>.</p>

<p>Return<em> the sum of the</em> <code>k</code> <em>integers appended to</em> <code>nums</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,4,25,10,25], k = 2
<strong>Output:</strong> 5
<strong>Explanation:</strong> The two unique positive integers that do not appear in nums which we append are 2 and 3.
The resulting sum of nums is 1 + 4 + 25 + 10 + 25 + 2 + 3 = 70, which is the minimum.
The sum of the two integers appended is 2 + 3 = 5, so we return 5.</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> nums = [5,6], k = 6
<strong>Output:</strong> 25
<strong>Explanation:</strong> The six unique positive integers that do not appear in nums which we append are 1, 2, 3, 4, 7, and 8.
The resulting sum of nums is 5 + 6 + 1 + 2 + 3 + 4 + 7 + 8 = 36, which is the minimum. 
The sum of the six integers appended is 1 + 2 + 3 + 4 + 7 + 8 = 25, so we return 25.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= nums[i] &lt;= 10<sup>9</sup></code></li>
	<li><code>1 &lt;= k &lt;= 10<sup>8</sup></code></li>
</ul>

class Solution:
    def minimalKSum(self, nums: List[int], k: int) -> int:
        '''
        nums_set = set(nums)
        n = len(nums_set)

        #initial pruning
        i = 0
        while i < 1: # O(1) iters, O(n) overall. Can tune the iterations
            nums_set = {num for num in nums_set if num <= n+k} #O(n)
            new_n = len(nums_set)
            if n == new_n:
                break
            n = new_n
            i += 1

        #THIS BLOCK BRINGS K DOWN TO K' <= N' < N in O(N) time
        #at this point, nums_set has at most n_0 nums (if all unique), and they are between 1 and n_0+k_0. Call n at this point n_1, so nums_set has n_1 nums that are between 1 and n_1+k_0
        curr_sum = 0

        #initially enter below loop if k_0 >= n_1
        #k_1 is at most the number of elements less than k_0, which is at most n_1, in which case n_2 = 0 and we immediately terminate. We have k_1 + n_2 = n_1 -> k_1 = n_1 - n_2 <= n_1 <= k_0, and if k_1 = 0 then we also immediately terminate. 
        # this loop only executes a second time if k_1 >= n_2, which occurs when n_1 - n_2 >= n_2 aka n_2 <= n_1 / 2 which occurs when half of the n_1 unique numbers are less than k_0, leaving n_2 unique numbers that were satisfying k_0 < x <= n_1 + k_0 and are now satisfying 0 < x' <= n_1 = n_2 + k_2
        # Overall then, there can be O(log n) iterations though fairly unlikely. 
        # The overall worst case cost is something like m(n_0 + n_0 / 2 + n_0 / 4 + .. ) = m n_0 (1 + 1/2 + ...) = 3 m n -> O(n_1)
        while k >= n:
            if n == 0:
                return curr_sum + k*(k+1)//2
            small_nums_set = set(num for num in nums_set if num <= k) #O(n_i)
            len_small_nums = len(small_nums_set) #O(n_i)
            nums_set = set(num - k for num in nums_set.difference(small_nums_set)) #O(n_i)
            n = len(nums_set) #O(n)
            curr_sum += (k)*(k+1)//2 - sum(small_nums_set) + len_small_nums * k #O(n_i)
            k = len_small_nums #k must decrease
            if k == 0:
                return curr_sum
        '''
        curr_sum = 0
        curr_sum += k * (k + 1) // 2
        nums_set = set(nums)
        last = k
        for num in nums_set:
            if num <= k:
                last += 1
                while last in nums_set:
                    last += 1
                curr_sum += last - num
        return curr_sum
484