#include <bits/stdc++.h>
using namespace std;
namespace Solve1 {
const int maxn = 100005;
const int spc = 4000005;
struct SegmentTree {
  int sumv[spc], lc[spc], rc[spc], rt[spc], np;
  void Initial() {
    np = 0;
    memset(rt, 0, sizeof(rt));
    memset(lc, 0, sizeof(lc));
    memset(rc, 0, sizeof(rc));
    memset(sumv, 0, sizeof(sumv));
    return;
  }
  int Copynode(int pre) {
    ++np;
    sumv[np] = sumv[pre];
    lc[np] = lc[pre], rc[np] = rc[pre];
    return np;
  }
  void pushup(int now) {
    if (!now) return;
    sumv[now] = sumv[lc[now]] + sumv[rc[now]];
    return;
  }
  void Build(int &now, int L, int R) {
    now = ++np;
    if (L == R) return;
    int m = (L + R) >> 1;
    Build(lc[now], L, m);
    Build(rc[now], m + 1, R);
    return;
  }
  void Update(int pre, int &now, int L, int R, int i, int d) {
    now = Copynode(pre);
    if (L == R && L == i) {
      sumv[now] += d;
      return;
    }
    int m = (L + R) >> 1;
    if (i <= m)
      Update(lc[pre], lc[now], L, m, i, d);
    else
      Update(rc[pre], rc[now], m + 1, R, i, d);
    pushup(now);
    return;
  }
  int Qpos(int now, int L, int R, int k) {
    int low = L, upp = R, mid = -1, ret = -1;
    while (low < upp) {
      int mid = (low + upp) >> 1;
      if (sumv[lc[now]] <= k)
        k -= sumv[lc[now]], ret = mid, low = mid + 1, now = rc[now];
      else
        upp = mid, now = lc[now];
    }
    if (low == upp && sumv[now] <= k) ret = low;
    return ret;
  }
} ST;
int n, cnt, A[maxn], B[maxn];
int first[maxn], next[maxn], last[maxn];
void work() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &A[i]);
  memcpy(B, A, sizeof(B));
  cnt = 1;
  sort(B + 1, B + n + 1);
  for (int i = 2; i <= n; i++)
    if (B[i] != B[i - 1]) B[++cnt] = B[i];
  for (int i = 1; i <= n; i++) A[i] = lower_bound(B + 1, B + cnt + 1, A[i]) - B;
  ST.Initial();
  ST.Build(ST.rt[1], 1, n);
  memset(next, 0, sizeof(next));
  memset(last, 0, sizeof(last));
  memset(first, 0, sizeof(first));
  for (int i = 1; i <= n; i++) {
    if (!first[A[i]])
      first[A[i]] = last[A[i]] = next[i] = i;
    else
      next[last[A[i]]] = i, last[A[i]] = i;
  }
  for (int i = 1; i <= n; i++) {
    if (i == first[A[i]]) ST.Update(ST.rt[1], ST.rt[1], 1, n, i, 1);
  }
  for (int i = 1; i < n; i++) {
    ST.rt[i + 1] = ST.rt[i];
    if (i == last[A[i]])
      ST.Update(ST.rt[i + 1], ST.rt[i + 1], 1, n, i, -1);
    else {
      ST.Update(ST.rt[i + 1], ST.rt[i + 1], 1, n, next[i], 1);
      ST.Update(ST.rt[i + 1], ST.rt[i + 1], 1, n, i, -1);
    }
  }
  for (int k = 1; k <= n; k++) {
    int now = 1, ans = 0;
    while (now <= n) {
      ans++;
      now = ST.Qpos(ST.rt[now], 1, n, k) + 1;
    }
    printf("%d ", ans);
  }
  printf("\n");
  return;
}
}  // namespace Solve1
int main() {
  Solve1::work();
  return 0;
}
