#pragma region Macros
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                \
    vector<type> name(size);                                                                                \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                \
    vector<vector<type>> name(h, vector<type>(w));                                                                                \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define Size(c) (int)(c).size()
#define INT(...)                                                                                \
    int __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LL(...)                                                                                \
    ll __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define ULL(...)                                                                                \
    ull __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define STR(...)                                                                                \
    string __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                \
    char __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                \
    double __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LD(...)                                                                                \
    ld __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
template <class T> void scan(T a) { cin >> a; }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(long double &a) { cin >> a; }
void scan(char a[]) { scanf("%s", a); }
void scan(string &a) { cin >> a; }
template <class T> void scan(vector<T> &);
template <class T, size_t size> void scan(array<T, size> &);
template <class T, class L> void scan(pair<T, L> &);
template <class T, size_t size> void scan(T (&)[size]);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(deque<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T, size_t size> void scan(array<T, size> &a) {
    for(auto &i : a) scan(i);
}
template <class T, class L> void scan(pair<T, L> &p) {
    scan(p.first);
    scan(p.second);
}
template <class T, size_t size> void scan(T (&a)[size]) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
string stin() {
    string s;
    cin >> s;
    return s;
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <class T> void UNIQUE(vector<T> &x) {
    sort(all(x));
    x.erase(unique(all(x)), x.end());
}
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}
void print() { putchar(' '); }
void print(bool a) { cout << a; }
void print(int a) { cout << a; }
void print(long long a) { cout << a; }
void print(char a) { cout << a; }
void print(string &a) { cout << a; }
void print(double a) { cout << a; }
template <class T> void print(const vector<T> &);
template <class T, size_t size> void print(const array<T, size> &);
template <class T, class L> void print(const pair<T, L> &p);
template <class T, size_t size> void print(const T (&)[size]);
template <class T> void print(const vector<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
    cout << endl;
}
template <class T> void print(const deque<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, size_t size> void print(const array<T, size> &a) {
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, class L> void print(const pair<T, L> &p) {
    cout << '(';
    print(p.first);
    cout << ",";
    print(p.second);
    cout << ')';
}
template <class T> void print(set<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T> void print(multiset<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T, size_t size> void print(const T (&a)[size]) {
    print(a[0]);
    for(auto i = a; ++i != end(a);) {
        cout << " ";
        print(*i);
    }
}
template <class T> void print(const T &a) { cout << a; }
int out() {
    putchar('\n');
    return 0;
}
template <class T> int out(const T &t) {
    print(t);
    putchar('\n');
    return 0;
}
template <class Head, class... Tail> int out(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
    return 0;
}
ll gcd(ll a, ll b) {
    while(b) {
        ll c = b;
        b = a % b;
        a = c;
    }
    return a;
}
ll lcm(ll a, ll b) {
    if(!a || !b) return 0;
    return a * b / gcd(a, b);
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
vector<int> divisor(int x) {
    vector<int> ans;
    for(int i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
template <typename T> void shuffle(vector<T> &v) {
    rep3(i, v.size() - 1, 1) { swap(v[i], v[rnd(i)]); }
}
#define endl '\n'
vector<string> YES{"NO", "YES"};
vector<string> Yes{"No", "Yes"};
vector<string> yes{"no", "yes"};

#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                \
    cout << #x << ": ";                                                                                \
    print(x);                                                                                \
    cout << endl;
void err() {}
template <class T> void err(const T &t) {
    print(t);
    cout << " ";
}
template <class Head, class... Tail> void err(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
}
#else
#define debug(x)
template <class... T> void err(const T &...) {}
#endif

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    // edge(int from,int to,T cost,int id):from(from),to(to),cost(cost),id(id){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};

template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedTree = vector<Edges<T>>;
template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedGraph = vector<Edges<T>>;
template <typename T> using Matrix = vector<vector<T>>;
using Graph = vector<vector<int>>;
using tree = vector<vector<int>>;

tree getTree(int n, int offset = 1) {
    tree res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template <typename T> WeightedTree<T> getWeightedTree(int n, int offset = 1) {
    WeightedTree<T> res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
    return res;
}

Graph getGraph(int n, int m, int offset = 1) {
    Graph res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}

template <typename T> WeightedGraph<T> getWeightedGraph(int n, int m, int offset = 1) {
    WeightedGraph<T> res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
}
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

// _________コーディングはここから！！___________
struct SuccinctIndexableDictionary {
    size_t length;
    size_t blocks;
    vector<unsigned> bit, sum;

    SuccinctIndexableDictionary() {}

    SuccinctIndexableDictionary(size_t _length) {
        length = _length;
        blocks = (length + 31) >> 5;
        bit.assign(blocks, 0U);
        sum.assign(blocks, 0U);
    }

    void set(int k) { bit[k >> 5] |= 1U << (k & 31); }

    void build() {
        sum[0] = 0U;
        for(int i = 1; i < blocks; i++) { sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]); }
    }

    bool operator[](int k) const { return (bool((bit[k >> 5] >> (k & 31)) & 1)); }

    int rank(int k) { return (sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1))); }

    int rank(bool val, int k) { return (val ? rank(k) : k - rank(k)); }

    int select(bool val, int k) {
        if(k < 0 || rank(val, length) <= k) return (-1);
        int low = 0, high = length;
        while(high - low > 1) {
            int mid = (low + high) >> 1;
            if(rank(val, mid) >= k + 1)
                high = mid;
            else
                low = mid;
        }
        return (high - 1);
    }

    int select(bool val, int i, int l) { return select(val, i + rank(val, l)); }
};

template <class T, int MAXLOG> struct WaveletMatrix {
    size_t length;
    SuccinctIndexableDictionary matrix[MAXLOG];
    int zs[MAXLOG];
    int buff1[MAXLOG], buff2[MAXLOG];

    int freq_dfs(int d, int l, int r, T val, T a, T b) {
        if(l == r) return 0;
        if(d == MAXLOG) return (a <= val && val < b) ? r - l : 0;
        T nv = 1ULL << (MAXLOG - d - 1) | val, nnv = ((1ULL << (MAXLOG - d - 1)) - 1) | nv;
        if(nnv < a || b <= val) return 0;
        if(a <= val && nnv < b) return r - l;
        int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
        return freq_dfs(d + 1, l - lc, r - rc, val, a, b) + freq_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b);
    }

    WaveletMatrix(vector<T> data) {
        length = data.size();
        vector<T> l(length), r(length);
        for(int depth = 0; depth < MAXLOG; depth++) {
            matrix[depth] = SuccinctIndexableDictionary(length + 1);
            int left = 0, right = 0;
            for(int i = 0; i < length; i++) {
                bool k = (data[i] >> (MAXLOG - depth - 1)) & 1;
                if(k)
                    r[right++] = data[i], matrix[depth].set(i);
                else
                    l[left++] = data[i];
            }
            zs[depth] = left;
            matrix[depth].build();
            swap(l, data);
            for(int i = 0; i < right; i++) data[left + i] = r[i];
        }
    }

    T access(int k) {
        int ret = 0;
        bool bit;
        for(int depth = 0; depth < MAXLOG; depth++) {
            bit = matrix[depth][k];
            ret = (ret << 1) | bit;
            k = matrix[depth].rank(bit, k) + zs[depth] * bit;
        }
        return (ret);
    }

    int rank(T val, int k) {
        int l = 0, r = k;
        for(int depth = 0; depth < MAXLOG; depth++) {
            buff1[depth] = l, buff2[depth] = r;
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            l = matrix[depth].rank(bit, l) + zs[depth] * bit;
            r = matrix[depth].rank(bit, r) + zs[depth] * bit;
        }
        return (r - l);
    }

    int select(T val, int kth) {
        rank(val, length);
        for(int depth = MAXLOG - 1; depth >= 0; depth--) {
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            kth = matrix[depth].select(bit, kth, buff1[depth]);
            if(kth >= buff2[depth] || kth < 0) return (-1);
            kth -= buff1[depth];
        }
        return (kth);
    }

    int select(T val, int k, int l) { return select(val, k + rank(val, l)); }

    int quantile(int left, int right, int kth) {
        if(right - left <= kth || kth < 0) return (-1);
        T ret = 0;
        for(int depth = 0; depth < MAXLOG; depth++) {
            int l = matrix[depth].rank(1, left);
            int r = matrix[depth].rank(1, right);
            if(r - l > kth) {
                left = l + zs[depth];
                right = r + zs[depth];
                ret |= 1ULL << (MAXLOG - depth - 1);
            } else {
                kth -= r - l;
                left -= l;
                right -= r;
            }
        }
        return ret;
    }

    int rangefreq(int left, int right, T lower, T upper) { return freq_dfs(0, left, right, 0, lower, upper); }
};
main() {
    INT(n);
    VEC(int, a, n);
    vi pre(n + 1, -1);
    vi nxt(n + 1, n + 1);
    rep(i, n) {
        if(pre[a[i]] != -1) { nxt[pre[a[i]]] = i; }
        pre[a[i]] = i;
    }
    WaveletMatrix<int, 17> mat(nxt);
    rep2(i, 1, n) {
        int now = 0;
        int cnt = 0;
        while(now < n) {
            int l = now + i, r = n + 1;
            chmin(l, n);
            chmin(r, n + 1);
            while(l < r - 1) {
                int mid = (l + r) / 2;
                if(mid - now - mat.rangefreq(now, mid, now, mid) > i)
                    r = mid;
                else
                    l = mid;
            }
            cnt++;
            now = l;
        }
        cout << cnt << " ";
    }
    cout << endl;
}


#pragma region Macros
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                \
    vector<type> name(size);                                                                                \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                \
    vector<vector<type>> name(h, vector<type>(w));                                                                                \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define Size(c) (int)(c).size()
#define INT(...)                                                                                \
    int __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LL(...)                                                                                \
    ll __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define ULL(...)                                                                                \
    ull __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define STR(...)                                                                                \
    string __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                \
    char __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                \
    double __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LD(...)                                                                                \
    ld __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
template <class T> void scan(T a) { cin >> a; }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(long double &a) { cin >> a; }
void scan(char a[]) { scanf("%s", a); }
void scan(string &a) { cin >> a; }
template <class T> void scan(vector<T> &);
template <class T, size_t size> void scan(array<T, size> &);
template <class T, class L> void scan(pair<T, L> &);
template <class T, size_t size> void scan(T (&)[size]);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(deque<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T, size_t size> void scan(array<T, size> &a) {
    for(auto &i : a) scan(i);
}
template <class T, class L> void scan(pair<T, L> &p) {
    scan(p.first);
    scan(p.second);
}
template <class T, size_t size> void scan(T (&a)[size]) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
string stin() {
    string s;
    cin >> s;
    return s;
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <class T> void UNIQUE(vector<T> &x) {
    sort(all(x));
    x.erase(unique(all(x)), x.end());
}
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}
void print() { putchar(' '); }
void print(bool a) { cout << a; }
void print(int a) { cout << a; }
void print(long long a) { cout << a; }
void print(char a) { cout << a; }
void print(string &a) { cout << a; }
void print(double a) { cout << a; }
template <class T> void print(const vector<T> &);
template <class T, size_t size> void print(const array<T, size> &);
template <class T, class L> void print(const pair<T, L> &p);
template <class T, size_t size> void print(const T (&)[size]);
template <class T> void print(const vector<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
    cout << endl;
}
template <class T> void print(const deque<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, size_t size> void print(const array<T, size> &a) {
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, class L> void print(const pair<T, L> &p) {
    cout << '(';
    print(p.first);
    cout << ",";
    print(p.second);
    cout << ')';
}
template <class T> void print(set<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T> void print(multiset<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T, size_t size> void print(const T (&a)[size]) {
    print(a[0]);
    for(auto i = a; ++i != end(a);) {
        cout << " ";
        print(*i);
    }
}
template <class T> void print(const T &a) { cout << a; }
int out() {
    putchar('\n');
    return 0;
}
template <class T> int out(const T &t) {
    print(t);
    putchar('\n');
    return 0;
}
template <class Head, class... Tail> int out(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
    return 0;
}
ll gcd(ll a, ll b) {
    while(b) {
        ll c = b;
        b = a % b;
        a = c;
    }
    return a;
}
ll lcm(ll a, ll b) {
    if(!a || !b) return 0;
    return a * b / gcd(a, b);
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
vector<int> divisor(int x) {
    vector<int> ans;
    for(int i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
template <typename T> void shuffle(vector<T> &v) {
    rep3(i, v.size() - 1, 1) { swap(v[i], v[rnd(i)]); }
}
#define endl '\n'
vector<string> YES{"NO", "YES"};
vector<string> Yes{"No", "Yes"};
vector<string> yes{"no", "yes"};

#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                \
    cout << #x << ": ";                                                                                \
    print(x);                                                                                \
    cout << endl;
void err() {}
template <class T> void err(const T &t) {
    print(t);
    cout << " ";
}
template <class Head, class... Tail> void err(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
}
#else
#define debug(x)
template <class... T> void err(const T &...) {}
#endif

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    // edge(int from,int to,T cost,int id):from(from),to(to),cost(cost),id(id){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};

template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedTree = vector<Edges<T>>;
template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedGraph = vector<Edges<T>>;
template <typename T> using Matrix = vector<vector<T>>;
using Graph = vector<vector<int>>;
using tree = vector<vector<int>>;

tree getTree(int n, int offset = 1) {
    tree res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template <typename T> WeightedTree<T> getWeightedTree(int n, int offset = 1) {
    WeightedTree<T> res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
    return res;
}

Graph getGraph(int n, int m, int offset = 1) {
    Graph res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}

template <typename T> WeightedGraph<T> getWeightedGraph(int n, int m, int offset = 1) {
    WeightedGraph<T> res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
}
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

// _________コーディングはここから！！___________
struct SuccinctIndexableDictionary {
    size_t length;
    size_t blocks;
    vector<unsigned> bit, sum;

    SuccinctIndexableDictionary() {}

    SuccinctIndexableDictionary(size_t _length) {
        length = _length;
        blocks = (length + 31) >> 5;
        bit.assign(blocks, 0U);
        sum.assign(blocks, 0U);
    }

    void set(int k) { bit[k >> 5] |= 1U << (k & 31); }

    void build() {
        sum[0] = 0U;
        for(int i = 1; i < blocks; i++) { sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]); }
    }

    bool operator[](int k) const { return (bool((bit[k >> 5] >> (k & 31)) & 1)); }

    int rank(int k) { return (sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1))); }

    int rank(bool val, int k) { return (val ? rank(k) : k - rank(k)); }

    int select(bool val, int k) {
        if(k < 0 || rank(val, length) <= k) return (-1);
        int low = 0, high = length;
        while(high - low > 1) {
            int mid = (low + high) >> 1;
            if(rank(val, mid) >= k + 1)
                high = mid;
            else
                low = mid;
        }
        return (high - 1);
    }

    int select(bool val, int i, int l) { return select(val, i + rank(val, l)); }
};

template <class T, int MAXLOG> struct WaveletMatrix {
    size_t length;
    SuccinctIndexableDictionary matrix[MAXLOG];
    int zs[MAXLOG];
    int buff1[MAXLOG], buff2[MAXLOG];

    int freq_dfs(int d, int l, int r, T val, T a, T b) {
        if(l == r) return 0;
        if(d == MAXLOG) return (a <= val && val < b) ? r - l : 0;
        T nv = 1ULL << (MAXLOG - d - 1) | val, nnv = ((1ULL << (MAXLOG - d - 1)) - 1) | nv;
        if(nnv < a || b <= val) return 0;
        if(a <= val && nnv < b) return r - l;
        int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
        return freq_dfs(d + 1, l - lc, r - rc, val, a, b) + freq_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b);
    }

    WaveletMatrix(vector<T> data) {
        length = data.size();
        vector<T> l(length), r(length);
        for(int depth = 0; depth < MAXLOG; depth++) {
            matrix[depth] = SuccinctIndexableDictionary(length + 1);
            int left = 0, right = 0;
            for(int i = 0; i < length; i++) {
                if(data[i] == length + 1) continue;
                bool k = (data[i] >> (MAXLOG - depth - 1)) & 1;
                if(k)
                    r[right++] = data[i], matrix[depth].set(i);
                else
                    l[left++] = data[i];
            }
            zs[depth] = left;
            matrix[depth].build();
            swap(l, data);
            for(int i = 0; i < right; i++) data[left + i] = r[i];
        }
    }

    T access(int k) {
        int ret = 0;
        bool bit;
        for(int depth = 0; depth < MAXLOG; depth++) {
            bit = matrix[depth][k];
            ret = (ret << 1) | bit;
            k = matrix[depth].rank(bit, k) + zs[depth] * bit;
        }
        return (ret);
    }

    int rank(T val, int k) {
        int l = 0, r = k;
        for(int depth = 0; depth < MAXLOG; depth++) {
            buff1[depth] = l, buff2[depth] = r;
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            l = matrix[depth].rank(bit, l) + zs[depth] * bit;
            r = matrix[depth].rank(bit, r) + zs[depth] * bit;
        }
        return (r - l);
    }

    int select(T val, int kth) {
        rank(val, length);
        for(int depth = MAXLOG - 1; depth >= 0; depth--) {
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            kth = matrix[depth].select(bit, kth, buff1[depth]);
            if(kth >= buff2[depth] || kth < 0) return (-1);
            kth -= buff1[depth];
        }
        return (kth);
    }

    int select(T val, int k, int l) { return select(val, k + rank(val, l)); }

    int quantile(int left, int right, int kth) {
        if(right - left <= kth || kth < 0) return (-1);
        T ret = 0;
        for(int depth = 0; depth < MAXLOG; depth++) {
            int l = matrix[depth].rank(1, left);
            int r = matrix[depth].rank(1, right);
            if(r - l > kth) {
                left = l + zs[depth];
                right = r + zs[depth];
                ret |= 1ULL << (MAXLOG - depth - 1);
            } else {
                kth -= r - l;
                left -= l;
                right -= r;
            }
        }
        return ret;
    }

    int rangefreq(int left, int right, T lower, T upper) { return freq_dfs(0, left, right, 0, lower, upper); }
};
template <const int sz = 5 * 10000000, typename T = long long> struct IO {
    char reader[sz], writer[sz];
    char *now, *now2 = writer;
    IO() {
        reader[fread(reader, sizeof(char), sizeof(char) * sz, stdin)];
        now = reader;
    }
    inline T read() {
        while(*now && *now <= 32) now++;
        if(*now == '-') {
            now++;
            T res = 0;
            while('0' <= *now and *now <= '9') { res = res * 10 + *now++ - '0'; }
            return -res;
        } else {
            T res = 0;
            while('0' <= *now and *now <= '9') { res = res * 10 + *now++ - '0'; }
            return res;
        }
    }
    inline string read_str() {
        string res;
        while(*now and *now != '\n' and *now != ' ') res += *now++;
        now++;
        return res;
    }
    inline void write(T x, char margin = ' ') {
        if(x == 0) {
            putchar('0');
            putchar(margin);
            return;
        }
        if(x < 0) {
            putchar('-');
            x = -x;
        }
        while(x) {
            *now2 = '0' + x % 10;
            now2++;
            x /= 10;
        }
        do {
            now2--;
            putchar(*now2);
        } while(now2 != writer);
        putchar(margin);
    }
    inline void write_str(string s, char margin = ' ') {
        for(auto c : s) putchar(c);
        putchar(margin);
    }
};
IO io;
int a[101010];
main() {
    int n = io.read();
    rep(i,n) a[i] = io.read();
    vi pre(n + 1, -1);
    vi nxt(n , n + 1);
    rep(i, n) {
        if(pre[a[i]] != -1) { nxt[pre[a[i]]] = i; }
        pre[a[i]] = i;
    }
    WaveletMatrix<int, 17> mat(nxt);
    rep2(i, 1, n) {
        int now = 0;
        int cnt = 0;
        while(now < n) {
            int l = now + i, r = n + 1;
            chmin(l, n);
            chmin(r, n + 1);
            while(l < r - 1) {
                int mid = (l + r) / 2;
                if(mid - now - mat.rangefreq(now, mid, now, mid) > i)
                    r = mid;
                else
                    l = mid;
            }
            cnt++;
            now = l;
        }
        io.write(cnt," \n"[i==n]);
    }
}


#pragma region Macros
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define rep2(i, a, b) for(ll i = a; i <= b; ++i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define rep3(i, a, b) for(ll i = a; i >= b; --i)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                \
    vector<type> name(size);                                                                                \
    IN(name)
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                \
    vector<vector<type>> name(h, vector<type>(w));                                                                                \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define ios ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define Size(c) (int)(c).size()
#define INT(...)                                                                                \
    int __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LL(...)                                                                                \
    ll __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define ULL(...)                                                                                \
    ull __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define STR(...)                                                                                \
    string __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                \
    char __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                \
    double __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
#define LD(...)                                                                                \
    ld __VA_ARGS__;                                                                                \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
template <class T> void scan(T a) { cin >> a; }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(long double &a) { cin >> a; }
void scan(char a[]) { scanf("%s", a); }
void scan(string &a) { cin >> a; }
template <class T> void scan(vector<T> &);
template <class T, size_t size> void scan(array<T, size> &);
template <class T, class L> void scan(pair<T, L> &);
template <class T, size_t size> void scan(T (&)[size]);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(deque<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T, size_t size> void scan(array<T, size> &a) {
    for(auto &i : a) scan(i);
}
template <class T, class L> void scan(pair<T, L> &p) {
    scan(p.first);
    scan(p.second);
}
template <class T, size_t size> void scan(T (&a)[size]) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &... tail) {
    scan(head);
    IN(tail...);
}
string stin() {
    string s;
    cin >> s;
    return s;
}
template <class T, class S> inline bool chmax(T &a, S b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T, class S> inline bool chmin(T &a, S b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <class T> void UNIQUE(vector<T> &x) {
    sort(all(x));
    x.erase(unique(all(x)), x.end());
}
int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}
void print() { putchar(' '); }
void print(bool a) { cout << a; }
void print(int a) { cout << a; }
void print(long long a) { cout << a; }
void print(char a) { cout << a; }
void print(string &a) { cout << a; }
void print(double a) { cout << a; }
template <class T> void print(const vector<T> &);
template <class T, size_t size> void print(const array<T, size> &);
template <class T, class L> void print(const pair<T, L> &p);
template <class T, size_t size> void print(const T (&)[size]);
template <class T> void print(const vector<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
    cout << endl;
}
template <class T> void print(const deque<T> &a) {
    if(a.empty()) return;
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, size_t size> void print(const array<T, size> &a) {
    print(a[0]);
    for(auto i = a.begin(); ++i != a.end();) {
        cout << " ";
        print(*i);
    }
}
template <class T, class L> void print(const pair<T, L> &p) {
    cout << '(';
    print(p.first);
    cout << ",";
    print(p.second);
    cout << ')';
}
template <class T> void print(set<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T> void print(multiset<T> &x) {
    for(auto e : x) print(e), cout << " ";
    cout << endl;
}
template <class T, size_t size> void print(const T (&a)[size]) {
    print(a[0]);
    for(auto i = a; ++i != end(a);) {
        cout << " ";
        print(*i);
    }
}
template <class T> void print(const T &a) { cout << a; }
int out() {
    putchar('\n');
    return 0;
}
template <class T> int out(const T &t) {
    print(t);
    putchar('\n');
    return 0;
}
template <class Head, class... Tail> int out(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
    return 0;
}
ll gcd(ll a, ll b) {
    while(b) {
        ll c = b;
        b = a % b;
        a = c;
    }
    return a;
}
ll lcm(ll a, ll b) {
    if(!a || !b) return 0;
    return a * b / gcd(a, b);
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
vector<int> divisor(int x) {
    vector<int> ans;
    for(int i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    sort(all(y));
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
int popcount(ll x) { return __builtin_popcountll(x); }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int n) { return uniform_int_distribution<int>(0, n - 1)(rng); }
template <typename T> void shuffle(vector<T> &v) {
    rep3(i, v.size() - 1, 1) { swap(v[i], v[rnd(i)]); }
}
#define endl '\n'
vector<string> YES{"NO", "YES"};
vector<string> Yes{"No", "Yes"};
vector<string> yes{"no", "yes"};

#ifdef _LOCAL
#undef endl
#define debug(x)                                                                                \
    cout << #x << ": ";                                                                                \
    print(x);                                                                                \
    cout << endl;
void err() {}
template <class T> void err(const T &t) {
    print(t);
    cout << " ";
}
template <class Head, class... Tail> void err(const Head &head, const Tail &... tail) {
    print(head);
    putchar(' ');
    out(tail...);
}
#else
#define debug(x)
template <class... T> void err(const T &...) {}
#endif

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    // edge(int from,int to,T cost,int id):from(from),to(to),cost(cost),id(id){}
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};

template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedTree = vector<Edges<T>>;
template <typename T> using Edges = vector<edge<T>>;
template <typename T> using WeightedGraph = vector<Edges<T>>;
template <typename T> using Matrix = vector<vector<T>>;
using Graph = vector<vector<int>>;
using tree = vector<vector<int>>;

tree getTree(int n, int offset = 1) {
    tree res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}
template <typename T> WeightedTree<T> getWeightedTree(int n, int offset = 1) {
    WeightedTree<T> res(n);
    for(int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
    return res;
}

Graph getGraph(int n, int m, int offset = 1) {
    Graph res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        a -= offset, b -= offset;
        res[a].emplace_back(b);
        res[b].emplace_back(a);
    }
    return res;
}

template <typename T> WeightedGraph<T> getWeightedGraph(int n, int m, int offset = 1) {
    WeightedGraph<T> res(n);
    for(int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        T c;
        cin >> c;
        res[a].emplace_back(b, c);
        res[b].emplace_back(a, c);
    }
}
struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

// _________コーディングはここから！！___________
struct SuccinctIndexableDictionary {
    size_t length;
    size_t blocks;
    vector<unsigned> bit, sum;

    SuccinctIndexableDictionary() {}

    SuccinctIndexableDictionary(size_t _length) {
        length = _length;
        blocks = (length + 31) >> 5;
        bit.assign(blocks, 0U);
        sum.assign(blocks, 0U);
    }

    void set(int k) { bit[k >> 5] |= 1U << (k & 31); }

    void build() {
        sum[0] = 0U;
        for(int i = 1; i < blocks; i++) { sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]); }
    }

    bool operator[](int k) const { return (bool((bit[k >> 5] >> (k & 31)) & 1)); }

    int rank(int k) { return (sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1))); }

    int rank(bool val, int k) { return (val ? rank(k) : k - rank(k)); }

    int select(bool val, int k) {
        if(k < 0 || rank(val, length) <= k) return (-1);
        int low = 0, high = length;
        while(high - low > 1) {
            int mid = (low + high) >> 1;
            if(rank(val, mid) >= k + 1)
                high = mid;
            else
                low = mid;
        }
        return (high - 1);
    }

    int select(bool val, int i, int l) { return select(val, i + rank(val, l)); }
};

template <class T, int MAXLOG> struct WaveletMatrix {
    size_t length;
    SuccinctIndexableDictionary matrix[MAXLOG];
    int zs[MAXLOG];
    int buff1[MAXLOG], buff2[MAXLOG];

    int freq_dfs(int d, int l, int r, T val, T a, T b) {
        if(l == r) return 0;
        if(d == MAXLOG) return (a <= val && val < b) ? r - l : 0;
        T nv = 1ULL << (MAXLOG - d - 1) | val, nnv = ((1ULL << (MAXLOG - d - 1)) - 1) | nv;
        if(nnv < a || b <= val) return 0;
        if(a <= val && nnv < b) return r - l;
        int lc = matrix[d].rank(1, l), rc = matrix[d].rank(1, r);
        return freq_dfs(d + 1, l - lc, r - rc, val, a, b) + freq_dfs(d + 1, lc + zs[d], rc + zs[d], nv, a, b);
    }

    WaveletMatrix(vector<T> data) {
        length = data.size();
        vector<T> l(length), r(length);
        for(int depth = 0; depth < MAXLOG; depth++) {
            matrix[depth] = SuccinctIndexableDictionary(length + 1);
            int left = 0, right = 0;
            for(int i = 0; i < length; i++) {
                bool k = (data[i] >> (MAXLOG - depth - 1)) & 1;
                if(k)
                    r[right++] = data[i], matrix[depth].set(i);
                else
                    l[left++] = data[i];
            }
            zs[depth] = left;
            matrix[depth].build();
            swap(l, data);
            for(int i = 0; i < right; i++) data[left + i] = r[i];
        }
    }

    T access(int k) {
        int ret = 0;
        bool bit;
        for(int depth = 0; depth < MAXLOG; depth++) {
            bit = matrix[depth][k];
            ret = (ret << 1) | bit;
            k = matrix[depth].rank(bit, k) + zs[depth] * bit;
        }
        return (ret);
    }

    int rank(T val, int k) {
        int l = 0, r = k;
        for(int depth = 0; depth < MAXLOG; depth++) {
            buff1[depth] = l, buff2[depth] = r;
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            l = matrix[depth].rank(bit, l) + zs[depth] * bit;
            r = matrix[depth].rank(bit, r) + zs[depth] * bit;
        }
        return (r - l);
    }

    int select(T val, int kth) {
        rank(val, length);
        for(int depth = MAXLOG - 1; depth >= 0; depth--) {
            bool bit = (val >> (MAXLOG - depth - 1)) & 1;
            kth = matrix[depth].select(bit, kth, buff1[depth]);
            if(kth >= buff2[depth] || kth < 0) return (-1);
            kth -= buff1[depth];
        }
        return (kth);
    }

    int select(T val, int k, int l) { return select(val, k + rank(val, l)); }

    int quantile(int left, int right, int kth) {
        if(right - left <= kth || kth < 0) return (-1);
        T ret = 0;
        for(int depth = 0; depth < MAXLOG; depth++) {
            int l = matrix[depth].rank(1, left);
            int r = matrix[depth].rank(1, right);
            if(r - l > kth) {
                left = l + zs[depth];
                right = r + zs[depth];
                ret |= 1ULL << (MAXLOG - depth - 1);
            } else {
                kth -= r - l;
                left -= l;
                right -= r;
            }
        }
        return ret;
    }

    int rangefreq(int left, int right, T lower, T upper) { return freq_dfs(0, left, right, 0, lower, upper); }
};
template <const int sz = 5 * 10000000, typename T = long long> struct IO {
    char reader[sz], writer[sz];
    char *now, *now2 = writer;
    IO() {
        reader[fread(reader, sizeof(char), sizeof(char) * sz, stdin)];
        now = reader;
    }
    inline T read() {
        while(*now && *now <= 32) now++;
        if(*now == '-') {
            now++;
            T res = 0;
            while('0' <= *now and *now <= '9') { res = res * 10 + *now++ - '0'; }
            return -res;
        } else {
            T res = 0;
            while('0' <= *now and *now <= '9') { res = res * 10 + *now++ - '0'; }
            return res;
        }
    }
    inline string read_str() {
        string res;
        while(*now and *now != '\n' and *now != ' ') res += *now++;
        now++;
        return res;
    }
    inline void write(T x, char margin = ' ') {
        if(x == 0) {
            putchar('0');
            putchar(margin);
            return;
        }
        if(x < 0) {
            putchar('-');
            x = -x;
        }
        while(x) {
            *now2 = '0' + x % 10;
            now2++;
            x /= 10;
        }
        do {
            now2--;
            putchar(*now2);
        } while(now2 != writer);
        putchar(margin);
    }
    inline void write_str(string s, char margin = ' ') {
        for(auto c : s) putchar(c);
        putchar(margin);
    }
};
IO io;
int a[101010];
main() {
    int n = io.read();
    rep(i,n) a[i] = io.read();
    vi pre(n + 1, -1);
    vi nxt(n + 1, n + 1);
    rep(i, n) {
        if(pre[a[i]] != -1) { nxt[pre[a[i]]] = i; }
        pre[a[i]] = i;
    }
    WaveletMatrix<int, 17> mat(nxt);
    rep2(i, 1, n) {
        int now = 0;
        int cnt = 0;
        while(now < n) {
            int l = now + i, r = n + 1;
            chmin(l, n);
            chmin(r, n + 1);
            while(l < r - 1) {
                int mid = (l + r) / 2;
                if(mid - now - mat.rangefreq(now, mid, now, mid) > i)
                    r = mid;
                else
                    l = mid;
            }
            cnt++;
            now = l;
        }
        io.write(cnt," \n"[i==n]);
    }
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 1200;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		int32_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		int32_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_left()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 600;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 40000;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		int32_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_left()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 2000;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		int32_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_left()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 40000;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_left()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e4 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_left()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < n; i++) {
		std::cout << ans[i] << " \n"[i == (n - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 200;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 800;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 400;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 1000;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>

constexpr int MAXN = 1e5 + 5;
constexpr int k = 1500;

int input[MAXN], ans[MAXN];
int n;

class Data {
private:
	class Help {
	private:
		uint16_t data[MAXN];
		int cnt;
	public:
		Help() : cnt(0) {
			std::fill(data, data + MAXN, (uint16_t)0);
		}
		void reset() {
			std::fill(data, data + MAXN, uint16_t(0));
			cnt = 0;
		}
		void add(int val) {
			cnt += data[val]++ == 0;
		}
		void erase(int val) {
			cnt -= --data[val] == 0;
		}
		int get()const {
			return cnt;
		}
	};
	int left, right;//[left, right)
	Help data;
public:
	Data(int pos = 0) : left(pos), right(pos) { ; }
	void reset(int pos = 0) {
		if (left == right) {
			left = right = pos;
		}
		else {
			left = right = pos;
			data.reset();
		}
	}
	void push_right() {
		data.add(input[right++]);
	}
	void push_left() {
		data.add(input[--left]);
	}
	void pop_left() {
		data.erase(input[left++]);
	}
	void pop_right() {
		data.erase(input[--right]);
	}
	int get() {
		if (right > n) {
			return 1e6;
		}
		else {
			return data.get();
		}
	}
	int get_left()const {
		return left;
	}
	int get_right()const {
		return right;
	}
};

Data data[(MAXN - 1) / k + 5];

signed main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	std::cin >> n;
	const int NNN = n;
	for (int i = 0; i < n; i++) { std::cin >> input[i]; }
	n = std::unique(input, input + n) - input;

	for (int t = 0; t < std::min(k, n); t++) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data->get() <= (t + 1)) {
				data->push_right(); r++;
			}
			data->pop_right();
			r--;
			for (int f = l; f < r; f++) {
				data->pop_left();
			}
			ans[t]++;
		}
		data->reset();
	}
	if (k < n) {
		for (int r = 0; r < n; ) {
			int l = r;
			while (data[ans[k]].get() <= (k + 1)) {
				data[ans[k]].push_right(); r++;
			}
			data[ans[k]].pop_right();
			r--;
			data[++ans[k]].reset(r);
		}
		for (int t = k + 1; t < n; t++) {
			for (int i = 0; i < ans[t - 1]; i++) {
				while (data[i].get() <= (t + 1)) {
					data[i].push_right();
				}
				data[i].pop_right();

				if (data[i].get_right() == n) {
					ans[t] = i + (data[i].get_left() != data[i].get_right());
					break;
				}

				while (data[i + 1].get_right() < data[i].get_right()) {
					data[i + 1].push_right();
				}
				while (data[i + 1].get_left() < data[i].get_right()) {
					data[i + 1].pop_left();
				}
			}
		}
	}

	for (int i = 0; i < NNN; i++) {
		std::cout << std::max(ans[i], 1) << " \n"[i == (NNN - 1)];
	}

	std::cout.flush();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef int ll;
const ll N=(1LL<<17);
#define REP(i,n) for(ll i=0;i<n;++i)
#define REP1(i,n) for(ll i=1;i<=n;++i)

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=16;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll MOD=1e9+7;
const ll MOD2=998244353;
const ll N=(1LL<<18);
const ll INF=(1LL<<60);
const ld pi=3.14159265359;
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define setp setprecision
#define lwb lower_bound
#define SZ(a) (ll)a.size()

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=17;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll MOD=1e9+7;
const ll MOD2=998244353;
const ll N=(1LL<<17);
const ll INF=(1LL<<60);
const ld pi=3.14159265359;
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define setp setprecision
#define lwb lower_bound
#define SZ(a) (ll)a.size()

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=16;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef int ll;
const ll N=(1LL<<17);
#define REP(i,n) for(ll i=0;i<n;++i)
#define REP1(i,n) for(ll i=1;i<=n;++i)

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti==k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

void solve(ll l,ll r){
	if(l==r)return;
	ll tmp=get(l);
	if(tmp==get(r-1)){for(ll i=l;i<r;++i)ans[i]=tmp;return ;}
	ll mid=(l+r)/2;
	solve(l,mid);solve(mid,r);
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	solve(1,n+1);
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll MOD=1e9+7;
const ll MOD2=998244353;
const ll N=(1LL<<19);
const ll INF=(1LL<<60);
const ld pi=3.14159265359;
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define setp setprecision
#define lwb lower_bound
#define SZ(a) (ll)a.size()

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=18;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll MOD=1e9+7;
const ll MOD2=998244353;
const ll N=(1LL<<17);
const ll INF=(1LL<<60);
const ld pi=3.14159265359;
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define setp setprecision
#define lwb lower_bound
#define SZ(a) (ll)a.size()

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=16;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
const ll MOD=1e9+7;
const ll MOD2=998244353;
const ll N=(1LL<<22);
const ll INF=(1LL<<60);
const ld pi=3.14159265359;
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(ll i=1;i<=n;i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define setp setprecision
#define lwb lower_bound
#define SZ(a) (ll)a.size()

ll n,u[N],ans[N],c[N];

ll get(ll k){
	ll cnt=1,tti=0;memset(c,0,sizeof(c));
	REP1(i,n){
		if(c[u[i]]==cnt)continue;
		if(tti>=k){tti=0;++cnt;}
		c[u[i]]=cnt;++tti;
	}
	return cnt;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	REP1(i,n)cin>>u[i];
	for(ll i=1;i<=n;){
		ll ti=i,tmp=get(i);
		for(ll j=19;j>=0;j--){
			if(ti+(1LL<<j)>n)continue;
			if(tmp==get(ti+(1LL<<j))){
				ti+=(1LL<<j);
			}
		}
		while(i<=ti)ans[i++]=tmp;
	}
	REP1(i,n)cout<<ans[i]<<(i==n?"\n":" ");
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
//#pragma GCC optimize("O3")
//#pragma GCC target("sse4")
//#pragma GCC target("avx2")

#define deb(x) cout << #x << " = " << x << "\n"
#define all(x) (x).begin(), (x).end()
#define len(x) (int) x.size()
#define lsb(x) (x) & -(x)
#define l(x) (x << 1) + 1
#define r(x) (x << 1) + 2

#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound

using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ld, ld> pld;
typedef pair <ll, ll> pll;

template <class T1, class T2 = less <T1>> using pb_heap = __gnu_pbds::priority_queue <T1, T2, binary_heap_tag>;
template <class T1, class T2 = null_type, class T3 = less <T1>> using pb_map = tree <T1, T2, T3, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1, class T2 = null_type, class T3 = hash <T1>> using pb_umap = gp_hash_table <T1, T2, T3>;
template <class T1, class T2, class T3 = hash <T1>> using umap = unordered_map <T1, T2, T3>;
template <class T> using uset = unordered_set <T>;
template <class T> using vec = vector <T>;

const ll infll = numeric_limits <ll>::max() >> 1;
const int inf = numeric_limits <int>::max() >> 1;
const int N = 1e5 + 1;
int ans[N];
int arr[N];
int n;

bool vis[N] = {0};
vec <int> con;

void input() {
    cin >> n;
    for(int i = 1; i <= n; ++i) {
        cin >> arr[i];
    }
}

int calc(int k) {
    int dif = 0;
    int res = 1;
    for(int i = 1; i <= n; ++i) {
        if(!vis[arr[i]]) {
            vis[arr[i]] = 1;
            if(++dif > k) {
                for(int e: con) {
                    vis[e] = 0;
                }
                con.clear();
                dif = 1;
                res++;
            }
            con.pb(arr[i]);
        }
    }
    for(int e: con) {
        vis[e] = 0;
    }
    con.clear();
    return res;
}

int bin_search(int l, int r, int k) {
    if(l == r) {
        return l;
    }
    int q = l + r + 1 >> 1;
    if(calc(q) == k) {
        return bin_search(q, r, k);
    } else {
        return bin_search(l, q - 1, k);
    }
}

void solve() {
    fill(ans, ans + N, inf);
    for(int i = 1; i <= n; ) {
        int k = calc(i);
        int q = bin_search(i, n, k);
        ans[i] = k;
        i = q + 1;
    }
    for(int i = 1; i <= n; ++i) {
        ans[i] = min(ans[i], ans[i - 1]);
        cout << ans[i] << " ";
    }
    cout << "\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    input();
    solve();
}