#include <bits/stdc++.h>
using namespace std;
template <typename T>
void _R(T &x) {
  cin >> x;
}
void _R(int &x) { scanf("%d", &x); }
void _R(long long &x) { scanf("%" PRId64, &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template <typename T, typename... U>
void R(T &head, U &...tail) {
  _R(head);
  R(tail...);
}
template <typename T>
void _W(const T &x) {
  cout << x;
}
void _W(const int &x) { printf("%d", x); }
void _W(const long long &x) { printf("%" PRId64, x); }
template <typename T>
void _W(const vector<T> &x) {
  for (auto i = x.cbegin(); i != x.cend(); i++) {
    if (i != x.cbegin()) putchar(' ');
    _W(*i);
  }
}
void W() {}
template <typename T, typename... U>
void W(const T &head, const U &...tail) {
  _W(head);
  putchar(sizeof...(tail) ? ' ' : '\n');
  W(tail...);
}
struct SplitMix32 {
  uint32_t s;
  SplitMix32(uint32_t _s = 0) : s(_s) {}
  uint32_t operator()() {
    uint32_t z = (s += 0x9e3779b1);
    z = (z ^ (z >> 16)) * 0x85ebca6b;
    z = (z ^ (z >> 13)) * 0xc2b2ae35;
    return z ^ (z >> 16);
  }
} rnd;
const int N = 1e5 + 10;
const int T = 500;
const int M = 217;
struct C {
  int c[N], m;
  vector<int> v;
  void clear() {
    m = 0;
    for (int i : v) c[i] = 0;
    v.clear();
  }
  void ins(int x) {
    if (c[x]++ == 0) m++;
    v.push_back(x);
  }
  void del(int x) {
    if (--c[x] == 0) m--;
  }
};
struct P {
  int l, r;
  C c;
  void clear(int a[]) {
    for (int i = (l); i <= int(r); i++) c.c[a[i]] = 0;
    c.m = 0;
  }
} p[M];
int n, a[N], sol[N];
int naive(int k) {
  static C c;
  int ans = 1;
  for (int i = (1); i <= int(n); i++) {
    c.ins(a[i]);
    if (c.m > k) {
      c.clear();
      ans++;
      c.ins(a[i]);
    }
  }
  c.clear();
  return ans;
}
int main() {
  R(n);
  for (int i = (1); i <= int(n); i++) R(a[i]);
  int t = min(n, T);
  for (int i = (1); i <= int(t); i++) sol[i] = naive(i);
  if (t + 1 <= n) {
    int m = 1;
    p[0].l = 1;
    for (int i = (1); i <= int(n); i++) {
      p[m - 1].c.ins(a[i]);
      if (p[m - 1].c.m > t + 1) {
        p[m - 1].c.del(a[i]);
        p[m - 1].r = i - 1;
        m++;
        p[m - 1].l = i;
        p[m - 1].c.ins(a[i]);
      }
    }
    p[m - 1].r = n;
    assert(m < M);
    sol[t + 1] = m;
    for (int i = (t + 2); i <= int(n); i++) {
      for (int j = 0; j < int(m); j++) {
        if (j > 0) {
          if (p[j - 1].r >= p[j].r) {
            p[j].clear(a);
            p[j].l = p[j - 1].r + 1;
            p[j].r = p[j].l;
            p[j].c.ins(a[p[j].r]);
          } else {
            while (p[j].l <= p[j - 1].r) {
              p[j].c.del(a[p[j].l]);
              p[j].l++;
            }
          }
        }
        while (p[j].r < n && p[j].c.m <= i) {
          p[j].r++;
          p[j].c.ins(a[p[j].r]);
        }
        if (p[j].c.m > i) {
          p[j].c.del(a[p[j].r]);
          p[j].r--;
        }
        if (p[j].r == n) {
          m = j + 1;
          break;
        }
      }
      sol[i] = m;
    }
  }
  for (int i = (1); i <= int(n); i++)
    printf("%d%c", sol[i], i == n ? '\n' : ' ');
  return 0;
}
