← Home
```go
package main

import (
	"bufio"
	"os"
	"strconv"
)

func main() {
	// Initialize fast I/O
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	// Helper function to read next integer
	readInt := func() int {
		scanner.Scan()
		x, _ := strconv.Atoi(scanner.Text())
		return x
	}

	if !scanner.Scan() {
		return
	}
	t, _ := strconv.Atoi(scanner.Text())

	for ; t > 0; t-- {
		n := readInt()

		// Read array and count frequencies
		counts := make([]int, n+1)
		for i := 0; i < n; i++ {
			counts[readInt()]++
		}

		// Count how many values have a specific frequency (bucket sort concept)
		freqOfFreq := make([]int, n+1)
		for v := 1; v <= n; v++ {
			if c := counts[v]; c > 0 {
				freqOfFreq[c]++
			}
		}

		// Construct c: frequencies sorted in descending order
		// Using 1-based indexing for convenient prefix sums
		c := make([]int, 1, n+1)
		for f := n; f >= 1; f-- {
			cnt := freqOfFreq[f]
			for k := 0; k < cnt; k++ {
				c = append(c, f)
			}
		}
		D := len(c) - 1 // Number of distinct values

		// P: Prefix sums of sorted frequencies c
		P := make([]int, D+1)
		for k := 1; k <= D; k++ {
			P[k] = P[k-1] + c[k]
		}

		// cPrime: Conjugate partition of c
		// cPrime[x] is the number of values with frequency >= x
		cPrime := make([]int, n+2)
		cur := 0
		for x := n; x >= 1; x-- {
			cur += freqOfFreq[x]
			cPrime[x] = cur
		}

		// PPrime: Prefix sums of cPrime
		// PPrime[j] = sum(cPrime[x] for x=1 to j) = sum(min(c_k, j))
		PPrime := make([]int, n+2)
		for x := 1; x <= n+1; x++ {
			PPrime[x] = PPrime[x-1] + cPrime[x]
		}

		// ans[k] will store the minimum operations to remove exactly k elements
		ans := make([]int, n+1)
		lastRemoved := 0

		// Iterate on the number of operations M
		// We calculate maxRem(M), the maximum elements we can remove in M operations.
		// Since maxRem(M) is non-decreasing, we can fill the answers for ranges.
		for M := 1; lastRemoved < n; M++ {
			maxRem := 0
			// We can split M operations into i operations of Type 1 (removing specific values)
			// and j = M - i operations of Type 2 (removing distinct sets).
			
			// Limit i by D because we can't choose more distinct values than available.
			limitI := M
			if limitI > D {
				limitI = D
			}

			for i := 0; i <= limitI; i++ {
				j := M - i
				
				// Calculate contribution from j Type 2 operations
				// This removes min(count[v], j) for all v.
				// This equals sum of first j columns of the Ferrers diagram => PPrime[j]
				var term1 int
				if j >= n+1 {
					term1 = PPrime[n+1]
				} else {
					term1 = PPrime[j]
				}

				// Calculate contribution from i Type 1 operations
				// We pick i values with the largest remaining counts after j Type 2 ops.
				// Remaining count for value k is max(0, c[k] - j).
				// We sum this for the largest i values.
				// c[k] - j > 0 implies c[k] > j, which implies k <= cPrime[j+1].
				
				var p int
				if j < n {
					p = cPrime[j+1]
				} else {
					p = 0
				}

				// We sum (c[k] - j) for k from 1 to min(i, p)
				lim := i
				if p < lim {
					lim = p
				}
				
				// Sum is (sum(c[k]) for k=1..lim) - lim * j
				term2 := P[lim] - lim*j
				
				currentTotal := term1 + term2
				if currentTotal > maxRem {
					maxRem = currentTotal
				}
			}

			if maxRem > n {
				maxRem = n
			}

			// If we can remove more elements with M ops than with M-1, update answers
			if maxRem > lastRemoved {
				for k := lastRemoved + 1; k <= maxRem; k++ {
					ans[k] = M
				}
				lastRemoved = maxRem
			}
		}

		// Output results for remaining size x = 0 to n-1
		// Remaining size x corresponds to removing n-x elements.
		for x := 0; x < n; x++ {
			if x > 0 {
				writer.WriteByte(' ')
			}
			writer.WriteString(strconv.Itoa(ans[n-x]))
		}
		writer.WriteByte('\n')
	}
}
```