#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 5;
const int inf = 0x3f3f3f3f;
struct Segment_Tree {
  int n;
  int mn[MAXN << 2], tag[MAXN << 2];
  inline void push_up(int u) {
    mn[u] = min(mn[((u) << 1)], mn[((u) << 1 | 1)]);
  }
  inline void push_down(int u) {
    if (tag[u]) {
      mn[((u) << 1)] += tag[u];
      tag[((u) << 1)] += tag[u];
      mn[((u) << 1 | 1)] += tag[u];
      tag[((u) << 1 | 1)] += tag[u];
      tag[u] = 0;
    }
  }
  void build(int u, int l, int r, vector<int> &val) {
    tag[u] = 0;
    if (l == r) {
      mn[u] = val[l];
      return;
    }
    int mid = (l + r) >> 1;
    build(((u) << 1), l, mid, val);
    build(((u) << 1 | 1), mid + 1, r, val);
    push_up(u);
  }
  inline void build(vector<int> &val) {
    n = (int)val.size();
    build(1, 0, n - 1, val);
  }
  void update(int u, int l, int r, int ql, int qr, int k) {
    if (ql <= l && r <= qr) {
      mn[u] += k;
      tag[u] += k;
      return;
    }
    push_down(u);
    int mid = (l + r) >> 1;
    if (ql <= mid) update(((u) << 1), l, mid, ql, qr, k);
    if (mid < qr) update(((u) << 1 | 1), mid + 1, r, ql, qr, k);
    push_up(u);
  }
  inline void update(int ql, int qr, int k) { update(1, 0, n - 1, ql, qr, k); }
  int query(int u, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) return mn[u];
    push_down(u);
    int mid = (l + r) >> 1, res = inf;
    if (ql <= mid) res = min(res, query(((u) << 1), l, mid, ql, qr));
    if (mid < qr) res = min(res, query(((u) << 1 | 1), mid + 1, r, ql, qr));
    return res;
  }
  inline int query(int ql, int qr) { return query(1, 0, n - 1, ql, qr); }
};
int n;
int a[MAXN];
vector<int> posz;
int nxt[MAXN];
bool check(int k) {
  vector<int> rs(k);
  for (int i = 0; i < k; ++i) rs[i] = *(posz.end() - k + i);
  static int freq[MAXN];
  for (int i = 1; i <= n; ++i) freq[i] = 0;
  int ccnt = 0;
  static int cnt_clr[MAXN];
  for (int i = posz[0]; i <= n; ++i) {
    if (a[i] && ++freq[a[i]] == 1) ++ccnt;
    cnt_clr[i] = ccnt;
  }
  vector<int> val(k);
  for (int i = 0; i < k; ++i) {
    val[i] = cnt_clr[rs[i]] - (i + 1);
    if (val[i] < 0) return 0;
  }
  static Segment_Tree tree;
  tree.build(val);
  for (int i = 1; i < k; ++i) {
    for (int j = posz[i - 1] + 1; j < posz[i]; ++j)
      if (a[j]) {
        int r = lower_bound(rs.begin(), rs.end(), nxt[j]) - rs.begin() - 1;
        if (r < i) continue;
        tree.update(i, r, -1);
      }
    tree.update(i, k - 1, 1);
    if (tree.query(i, k - 1) < 0) return 0;
  }
  return 1;
}
void solve(void) {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
  posz.clear();
  for (int i = 1; i <= n; ++i)
    if (!a[i]) posz.push_back(i);
  if ((int)posz.size() <= 1 || !check(1)) {
    printf("0\n");
    return;
  }
  static int lst[MAXN];
  for (int i = 1; i <= n; ++i) lst[i] = n + 1;
  for (int i = n; i >= 1; --i)
    if (a[i]) {
      nxt[i] = lst[a[i]];
      lst[a[i]] = i;
    }
  int l = 1, r = (int)posz.size() / 2;
  while (l < r) {
    int mid = (l + r + 1) >> 1;
    if (check(mid))
      l = mid;
    else
      r = mid - 1;
  }
  printf("%d\n", l);
}
int main(void) {
  int T;
  scanf("%d", &T);
  while (T--) solve();
  return 0;
}
