← Home
package main

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

var scanner *bufio.Scanner
var out *bufio.Writer

func readInt() int {
	scanner.Scan()
	v, _ := strconv.Atoi(scanner.Text())
	return v
}

const INF = 1e9

type Edge struct {
	to  int
	cap int
	rev int
}

var graph [][]Edge
var level []int
var ptr []int
var q []int

func initDinic(n int) {
	if len(graph) < n {
		graph = make([][]Edge, n)
		level = make([]int, n)
		ptr = make([]int, n)
		q = make([]int, n)
	}
	for i := 0; i < n; i++ {
		graph[i] = graph[i][:0]
	}
}

func addEdge(from, to, cap int) {
	graph[from] = append(graph[from], Edge{to, cap, len(graph[to])})
	graph[to] = append(graph[to], Edge{from, 0, len(graph[from]) - 1})
}

func bfs(s, t, n int) bool {
	for i := 0; i < n; i++ {
		level[i] = -1
	}
	level[s] = 0
	head, tail := 0, 0
	q[tail] = s
	tail++
	for head < tail {
		v := q[head]
		head++
		for _, edge := range graph[v] {
			if edge.cap > 0 && level[edge.to] == -1 {
				level[edge.to] = level[v] + 1
				q[tail] = edge.to
				tail++
			}
		}
	}
	return level[t] != -1
}

func dfs(v, t, pushed int) int {
	if pushed == 0 || v == t {
		return pushed
	}
	for ptr[v] < len(graph[v]) {
		edge := &graph[v][ptr[v]]
		tr := edge.to
		if level[v]+1 != level[tr] || edge.cap == 0 {
			ptr[v]++
			continue
		}
		push := pushed
		if edge.cap < push {
			push = edge.cap
		}
		pushedFlow := dfs(tr, t, push)
		if pushedFlow == 0 {
			ptr[v]++
			continue
		}
		edge.cap -= pushedFlow
		graph[tr][edge.rev].cap += pushedFlow
		return pushedFlow
	}
	return 0
}

func maxFlow(s, t, n int) int {
	flow := 0
	for bfs(s, t, n) {
		for i := 0; i < n; i++ {
			ptr[i] = 0
		}
		for {
			pushed := dfs(s, t, INF)
			if pushed == 0 {
				break
			}
			flow += pushed
		}
	}
	return flow
}

var Occ [][]int
var vals []int
var Ul, Ur []int
var z int

func check(m int) bool {
	if m == 0 {
		return true
	}
	if 2*m > z {
		return false
	}

	F := 0
	Ul = Ul[:0]
	Ur = Ur[:0]

	for _, v := range vals {
		arr := Occ[v]
		idx := sort.Search(len(arr), func(i int) bool { return arr[i] >= m })

		if idx < len(arr) && arr[idx] <= z-m {
			F++
		} else {
			lv := 0
			if idx > 0 {
				lv = arr[idx-1]
			}
			rv := 0
			if idx < len(arr) {
				rv = z - arr[idx]
			}
			if lv > 0 || rv > 0 {
				Ul = append(Ul, lv)
				Ur = append(Ur, rv)
			}
		}
	}

	if F >= m {
		return true
	}

	k := m - F
	if k > len(Ul) {
		return false
	}

	nodes := 2*m + len(Ul)
	initDinic(nodes)
	S := 0
	T := 1

	for x := 1; x < m; x++ {
		addEdge(x+1, T, 1)
		if x > 1 {
			addEdge(x+1, x, INF)
		}
	}
	for y := 1; y < m; y++ {
		addEdge(m+y, T, 1)
		if y > 1 {
			addEdge(m+y, m+y-1, INF)
		}
	}

	for i := 0; i < len(Ul); i++ {
		vNode := 2*m + i
		addEdge(S, vNode, 1)
		if Ul[i] > 0 {
			addEdge(vNode, Ul[i]+1, 1)
		}
		if Ur[i] > 0 {
			addEdge(vNode, m+Ur[i], 1)
		}
	}

	flow := maxFlow(S, T, nodes)
	return flow >= k
}

func solve() {
	n := readInt()
	if len(Occ) < n+1 {
		newOcc := make([][]int, n+1)
		copy(newOcc, Occ)
		Occ = newOcc
	}
	for i := 0; i <= n; i++ {
		Occ[i] = Occ[i][:0]
	}

	z = 0
	for i := 0; i < n; i++ {
		v := readInt()
		if v == 0 {
			z++
		} else {
			Occ[v] = append(Occ[v], z)
		}
	}

	vals = vals[:0]
	for i := 1; i <= n; i++ {
		if len(Occ[i]) > 0 {
			vals = append(vals, i)
		}
	}

	low, high := 0, z/2
	ans := 0
	for low <= high {
		mid := (low + high) / 2
		if check(mid) {
			ans = mid
			low = mid + 1
		} else {
			high = mid - 1
		}
	}
	out.WriteString(strconv.Itoa(ans) + "\n")
}

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1024*1024), 1024*1024*10)
	out = bufio.NewWriter(os.Stdout)
	defer out.Flush()

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

	for i := 0; i < t; i++ {
		solve()
	}
}