#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/rope>
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
template<class L, class R>
istream &operator>>(istream &in, pair<L, R> &arr){
    return in >> arr.first >> arr.second;
}
template<class ...Args, template<class...> class T>
istream &operator>>(enable_if_t<!is_same_v<T<Args...>, string>, istream> &in, T<Args...> &arr){
	for(auto &x: arr) in >> x; return in;
}
template<class L, class R>
ostream &operator<<(ostream &out, const pair<L, R> &arr){
    return out << "(" << arr.first << ", " << arr.second << ")";
}
template<class ...Args, template<class...> class T>
ostream &operator<<(enable_if_t<!is_same_v<T<Args...>, string>, ostream> &out, const T<Args...> &arr){
	for(auto &x: arr) out << x << " "; return out << "\n";
}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rngll(chrono::steady_clock::now().time_since_epoch().count());
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
typedef long long ll;
typedef vector<int> vi; typedef vector<ll> vl; typedef vector<double> vd; typedef vector<string> vs;
typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<int, ll> pil; typedef pair<ll, int> pli;
typedef vector<pii> vpii; typedef vector<pil> vpil; typedef vector<pli> vpli; typedef vector<pll> vpll;
template<class T> T ctmax(T &x, const T &y){ return x = max(x, y);}
template<class T> T ctmin(T &x, const T &y){ return x = min(x, y);}
template<class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef tuple<int, int, int> tpl; typedef vector<tpl> vtpl;

template<class T>
struct node{
	node *l = 0, *r = 0;
	T val;
	node(T val): val(val){}
	node(node *l, node *r, function<T(T, T)> bin_op, T id): l(l), r(r), val(id){
		if(l) val = bin_op(l->val, val);
		if(r) val = bin_op(val, r->val);
	}
};
template<class T, class BO>
struct persistent_segment: vector<node<T> *>{
	int N;
	BO bin_op;
	const T id;
	persistent_segment(const vector<T> &arr, BO bin_op, T id): N(arr.size()), bin_op(bin_op), id(id){
		this->push_back(build(arr, 0, N));
	}
	node<T> *build(const vector<T> &arr, int left, int right){
		if(left + 1 == right) return new node<T>(arr[left]);
		int mid = left + right >> 1;
		return new node<T>(build(arr, left, mid), build(arr, mid, right), bin_op, id);
	}
	T pq(node<T> *u, int left, int right, int ql, int qr){
		if(qr <= left || right <= ql) return id;
		if(ql <= left && right <= qr) return u->val;
		int mid = left + right >> 1;
		return bin_op(pq(u->l, left, mid, ql, qr), pq(u->r, mid, right, ql, qr));
	}
	T query(node<T> *u, int ql, int qr){
		return pq(u, 0, N, ql, qr);
	}
	node<T> *ps(node<T> *u, int left, int right, int p, int val){
		if(left + 1 == right) return new node<T>(val);
		int mid = left + right >> 1;
		if(mid > p) return new node<T>(ps(u->l, left, mid, p, val), u->r, bin_op, id);
		else return new node<T>(u->l, ps(u->r, mid, right, p, val), bin_op, id);
	}
	void set(node<T> *u, int p, int val){
		this->push_back(ps(u, 0, N, p, val));
	}
	// Below assumes T is an ordered field and node stores positive values
	template<class IO>
	int plb(node<T> *u, int left, int right, T val, IO inv_op){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(u->l->val < val) return plb(u->r, mid, right, inv_op(val, u->l->val), inv_op);
		else return plb(u->l, left, mid, val, inv_op);
	}
	template<class IO>
	int lower_bound(node<T> *u, T val, IO inv_op){ // min i such that query[0, i) >= val
		if(u->val < val) return N + 1;
		else return plb(u, 0, N, val, inv_op);
	}
	template<class IO>
	int lower_bound(node<T> *u, int i, T val, IO inv_op){
		return lower_bound(u, bin_op(val, query(u, 0, min(i, N))), inv_op);
	}
	template<class IO>
	int pub(node<T> *u, int left, int right, T val, IO inv_op){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(val < u->l->val) return pub(u->l, left, mid, val, inv_op);
		else return pub(u->r, mid, right, inv_op(val, u->l->val), inv_op);
	}
	template<class IO>
	int upper_bound(node<T> *u, T val, IO inv_op){ // min i such that query[0, i) > val
		if(val < u->val) return pub(u, 0, N, val, inv_op);
		else return N + 1;
	}
	template<class IO>
	int upper_bound(node<T> *u, int i, T val, IO inv_op){
		return upper_bound(u, bin_op(val, query(u, 0, min(i, N))), inv_op);
	}
};
template<class T>
struct less_than_k_query{ // for less-than-k query, it only deals with numbers in range [0, N)
	int N;
	vector<node<T> *> p;
	persistent_segment<int, plus<int>> tr;
	less_than_k_query(const vector<T> &arr, bool IS_DVQ = true): N(sz(arr)), p(N + 1), tr(vi(N), plus<int>{}, 0){
		vector<pair<T, int>> event(N);
		if(IS_DVQ){
			map<T, int> q;
			for(int i = 0; i < N; ++ i){
				event[i] = {(q.count(arr[i]) ? q[arr[i]] : -1), i};
				q[arr[i]] = i;
			}
		}
		else for(int i = 0; i < N; ++ i) event[i] = {arr[i], i};
		sort(all(event), greater<pii>{});
		tr.reserve(N);
		for(int i = 0; i <= N; ++ i){
			while(!event.empty() && event.back().first < i){
				tr.set(tr.back(), event.back().second, 1);
				event.pop_back();
			}
			p[i] = tr.back();
		}
	}
	// For distinct value query
	int query(int ql, int qr){
		return tr.query(p[ql], ql, qr);
	}
	int lower_bound(int ql, int cnt){ // min i such that # of distinct in [l, l + i) >= cnt
		return tr.lower_bound(p[ql], ql, cnt, minus<int>());
	}
	int upper_bound(int ql, int cnt){ // min i such that # of distinct in [l, l + i) > cnt
		return tr.upper_bound(p[ql], ql, cnt, minus<int>());
	}
	// For less-than-k query
	int query(int ql, int qr, int k){
		return tr.query(p[k], ql, qr);
	}
	int lower_bound(int ql, int k, int cnt){ // min i such that ( # of elements < k in [l, l + i) ) >= cnt
		return tr.lower_bound(p[k], k, cnt, minus<int>());
	}
	int upper_bound(int ql, int k, int cnt){ // min i such that ( # of elements < k in [l, l + i) ) > cnt
		return tr.upper_bound(p[k], k, cnt, minus<int>());
	}
};

template<class T, class BO, class IO>
struct fenwick: vector<T>{
	int N;
	BO bin_op;
	IO inv_op;
	T id;
	fenwick(const vector<T> &arr, BO bin_op, IO inv_op, T id): N(arr.size()), bin_op(bin_op), inv_op(inv_op), id(id){
		this->resize(N + 1, id);
		for(int i = 0; i < N; ++ i) update(i, arr[i]);
	}
	void update(int p, T val){
		for(p ++; p <= N; p += p & -p) (*this)[p] = bin_op((*this)[p], val);
	}
	T sum(int p){
		T res = id;
		for(p ++; p > 0; p -= p & -p) res = bin_op(res, (*this)[p]);
		return res;
	}
	T query(int l, int r){
		return inv_op(sum(r - 1), sum(l - 1));
	}
};

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int n;
	cin >> n;
	vi a(n);
	cin >> a;
	less_than_k_query q(a);
	for(int k = 1; k <= n; ++ k){
		int res = 0;
		for(int i = 0; i < n; ){
			res ++;
			int j = q.upper_bound(i, k) - 1;
			i = j;
		}
		cout << res << " ";
	}
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<class L, class R>
istream &operator>>(istream &in, pair<L, R> &arr){
    return in >> arr.first >> arr.second;
}
template<class ...Args, template<class...> class T>
istream &operator>>(enable_if_t<!is_same_v<T<Args...>, string>, istream> &in, T<Args...> &arr){
	for(auto &x: arr) in >> x; return in;
}
template<class L, class R>
ostream &operator<<(ostream &out, const pair<L, R> &arr){
    return out << "(" << arr.first << ", " << arr.second << ") ";
}
template<class ...Args, template<class...> class T>
ostream &operator<<(enable_if_t<!is_same_v<T<Args...>, string>, ostream> &out, const T<Args...> &arr){
	for(auto &x: arr) out << x << " "; return out << "\n";
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
typedef long long ll;
typedef vector<int> vi; typedef vector<ll> vl; typedef vector<double> vd; typedef vector<string> vs;
typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<int, ll> pil; typedef pair<ll, int> pli;
typedef vector<pii> vpii; typedef vector<pil> vpil; typedef vector<pli> vpli; typedef vector<pll> vpll;
template<class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef tuple<int, int, int> tpl; typedef vector<tpl> vtpl;

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int n;
	cin >> n;
	vi a(n);
	cin >> a;
	for(auto &x: a){
		x --;
	}
	vi res(n + 1);
	auto calc = [&](int x){
		vi flag(n, true);
		int ans = 0;
		for(int i = 0, cur = 0; i < n; ){
			ans ++;
			int j = i;
			while(j < n && cur + flag[a[j]] <= x){
				cur += flag[a[j]];
				flag[a[j ++]] = false;
			}
			for(int k = i; k < j; ++ k){
				flag[a[k]] = true;
			}
			cur = 0;
			i = j;
		}
		return ans;
	};
	function<void(int, int)> solve = [&](int l, int r){
		if(l >= r) return;
		int m = l + r >> 1;
		if(res[l - 1] == res[r]){
			for(int i = l; i < r; ++ i){
				res[i] = res[r];
			}
			return;
		}
		res[m] = calc(m);
		solve(l, m), solve(m + 1, r);
	};
	res[1] = calc(1), res[n] = calc(n);
	solve(2, n);
	res.erase(res.begin());
	cout << res;
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<class L, class R>
istream &operator>>(istream &in, pair<L, R> &arr){
    return in >> arr.first >> arr.second;
}
template<class ...Args, template<class...> class T>
istream &operator>>(enable_if_t<!is_same_v<T<Args...>, string>, istream> &in, T<Args...> &arr){
	for(auto &x: arr) in >> x; return in;
}
template<class L, class R>
ostream &operator<<(ostream &out, const pair<L, R> &arr){
    return out << "(" << arr.first << ", " << arr.second << ") ";
}
template<class ...Args, template<class...> class T>
ostream &operator<<(enable_if_t<!is_same_v<T<Args...>, string>, ostream> &out, const T<Args...> &arr){
	for(auto &x: arr) out << x << " "; return out << "\n";
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
typedef long long ll;
typedef vector<int> vi; typedef vector<ll> vl; typedef vector<double> vd; typedef vector<string> vs;
typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<int, ll> pil; typedef pair<ll, int> pli;
typedef vector<pii> vpii; typedef vector<pil> vpil; typedef vector<pli> vpli; typedef vector<pll> vpll;
template<class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef tuple<int, int, int> tpl; typedef vector<tpl> vtpl;

template<class T>
struct node{
	node *l = 0, *r = 0;
	T val;
	node(T val): val(val){}
	node(node *l, node *r, function<T(T, T)> bin_op, T id): l(l), r(r), val(id){
		if(l) val = bin_op(l->val, val);
		if(r) val = bin_op(val, r->val);
	}
};
template<class T, class BO>
struct persistent_segment: vector<node<T> *>{
	int N;
	BO bin_op;
	const T id;
	persistent_segment(const vector<T> &arr, BO bin_op, T id): N(arr.size()), bin_op(bin_op), id(id){
		this->push_back(build(arr, 0, N));
	}
	node<T> *build(const vector<T> &arr, int left, int right){
		if(left + 1 == right) return new node<T>(arr[left]);
		int mid = left + right >> 1;
		return new node<T>(build(arr, left, mid), build(arr, mid, right), bin_op, id);
	}
	T pq(node<T> *u, int left, int right, int ql, int qr){
		if(qr <= left || right <= ql) return id;
		if(ql <= left && right <= qr) return u->val;
		int mid = left + right >> 1;
		return bin_op(pq(u->l, left, mid, ql, qr), pq(u->r, mid, right, ql, qr));
	}
	T query(node<T> *u, int ql, int qr){
		return pq(u, 0, N, ql, qr);
	}
	node<T> *ps(node<T> *u, int left, int right, int p, int val){
		if(left + 1 == right) return new node<T>(val);
		int mid = left + right >> 1;
		if(mid > p) return new node<T>(ps(u->l, left, mid, p, val), u->r, bin_op, id);
		else return new node<T>(u->l, ps(u->r, mid, right, p, val), bin_op, id);
	}
	void set(node<T> *u, int p, int val){
		this->push_back(ps(u, 0, N, p, val));
	}
	// Below assumes T is an ordered field and node stores positive values
	int plb(node<T> *u, int left, int right, T val){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(u->l->val < val) return plb(u->r, mid, right, val - u->l->val);
		else return plb(u->l, left, mid, val);
	}
	int lower_bound(node<T> *u, T val){ // min i such that query[0, i) >= val
		if(u->val < val) return N + 1;
		return plb(u, 0, N, val);
	}
	int pub(node<T> *u, int left, int right, T val){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(u->l->val <= val) return pub(u->r, mid, right, val - u->l->val);
		else return pub(u->l, left, mid, val);
	}
	int upper_bound(node<T> *u, T val){ // min i such that query[0, i) > val
		if(u->val <= val) return N + 1;
		return pub(u, 0, N, val);
	}
};
template<class T>
struct distinct_value_query{
	int N;
	vector<node<T> *> p;
	persistent_segment<int, plus<int>> tr;
	distinct_value_query(const vector<T> &arr): N(sz(arr)), p(N), tr(vi(N), plus<int>{}, 0){
		map<T, int> q;
		vpii t(N);
		for(int i = 0; i < N; ++ i){
			t[i] = {(q.count(arr[i]) ? q[arr[i]] : -1), i};
			q[arr[i]] = i;
		}
		sort(all(t), greater<pii>{});
		tr.reserve(N);
		for(int i = 0; i < N; ++ i){
			while(!t.empty() && t.back().first < i){
				tr.set(tr.back(), t.back().second, 1);
				t.pop_back();
			}
			p[i] = tr.back();
		}
	}
	int query(int l, int r){
		return tr.query(p[l], l, r);
	}
	int lower_bound(int l, int k){
		return tr.lower_bound(p[l], k + tr.query(p[l], 0, l));
	}
	int upper_bound(int l, int k){
		return tr.upper_bound(p[l], k + tr.query(p[l], 0, l));
	}
};

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int n;
	cin >> n;
	vi a(n);
	cin >> a;
	distinct_value_query q(a);
	for(int k = 1; k <= n; ++ k){
		int res = 0;
		for(int i = 0; i < n; ){
			res ++;
			int j = q.upper_bound(i, k) - 1;
			i = j;
		}
		cout << res << " ";
	}
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<class L, class R>
istream &operator>>(istream &in, pair<L, R> &arr){
    return in >> arr.first >> arr.second;
}
template<class ...Args, template<class...> class T>
istream &operator>>(enable_if_t<!is_same_v<T<Args...>, string>, istream> &in, T<Args...> &arr){
	for(auto &x: arr) in >> x; return in;
}
template<class L, class R>
ostream &operator<<(ostream &out, const pair<L, R> &arr){
    return out << "(" << arr.first << ", " << arr.second << ") ";
}
template<class ...Args, template<class...> class T>
ostream &operator<<(enable_if_t<!is_same_v<T<Args...>, string>, ostream> &out, const T<Args...> &arr){
	for(auto &x: arr) out << x << " "; return out << "\n";
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
typedef long long ll;
typedef vector<int> vi; typedef vector<ll> vl; typedef vector<double> vd; typedef vector<string> vs;
typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<int, ll> pil; typedef pair<ll, int> pli;
typedef vector<pii> vpii; typedef vector<pil> vpil; typedef vector<pli> vpli; typedef vector<pll> vpll;
template<class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef tuple<int, int, int> tpl; typedef vector<tpl> vtpl;

static char BUFF[450 << 15];
void *operator new(size_t s){
	static size_t i = sizeof BUFF;
	assert(s < i);
	return (void *)&BUFF[i -= s];
}
void operator delete(void *){}
template<class T>
struct node{
	node *l = 0, *r = 0;
	T val;
	node(T val): val(val){}
	node(node *l, node *r, function<T(T, T)> bin_op, T id): l(l), r(r), val(id){
		if(l) val = bin_op(l->val, val);
		if(r) val = bin_op(val, r->val);
	}
};
template<class T, class BO>
struct persistent_segment: vector<node<T> *>{
	int N;
	BO bin_op;
	const T id;
	persistent_segment(const vector<T> &arr, BO bin_op, T id): N(arr.size()), bin_op(bin_op), id(id){
		this->push_back(build(arr, 0, N));
	}
	node<T> *build(const vector<T> &arr, int left, int right){
		if(left + 1 == right) return new node<T>(arr[left]);
		int mid = left + right >> 1;
		return new node<T>(build(arr, left, mid), build(arr, mid, right), bin_op, id);
	}
	T pq(node<T> *u, int left, int right, int ql, int qr){
		if(qr <= left || right <= ql) return id;
		if(ql <= left && right <= qr) return u->val;
		int mid = left + right >> 1;
		return bin_op(pq(u->l, left, mid, ql, qr), pq(u->r, mid, right, ql, qr));
	}
	T query(node<T> *u, int ql, int qr){
		return pq(u, 0, N, ql, qr);
	}
	node<T> *ps(node<T> *u, int left, int right, int p, int val){
		if(left + 1 == right) return new node<T>(val);
		int mid = left + right >> 1;
		if(mid > p) return new node<T>(ps(u->l, left, mid, p, val), u->r, bin_op, id);
		else return new node<T>(u->l, ps(u->r, mid, right, p, val), bin_op, id);
	}
	void set(node<T> *u, int p, int val){
		this->push_back(ps(u, 0, N, p, val));
	}
	// Below assumes T is an ordered field and node stores positive values
	int plb(node<T> *u, int left, int right, T val){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(u->l->val < val) return plb(u->r, mid, right, val - u->l->val);
		else return plb(u->l, left, mid, val);
	}
	int lower_bound(node<T> *u, T val){ // min i such that query[0, i) >= val
		if(u->val < val) return N + 1;
		return plb(u, 0, N, val);
	}
	int pub(node<T> *u, int left, int right, T val){
		if(left + 1 == right) return right;
		int mid = left + right >> 1;
		if(u->l->val <= val) return pub(u->r, mid, right, val - u->l->val);
		else return pub(u->l, left, mid, val);
	}
	int upper_bound(node<T> *u, T val){ // min i such that query[0, i) > val
		if(u->val <= val) return N + 1;
		return pub(u, 0, N, val);
	}
};
template<class T>
struct distinct_value_query{
	int N;
	vector<node<T> *> p;
	persistent_segment<int, plus<int>> tr;
	distinct_value_query(const vector<T> &arr): N(sz(arr)), p(N), tr(vi(N), plus<int>{}, 0){
		map<T, int> q;
		vpii t(N);
		for(int i = 0; i < N; ++ i){
			t[i] = {(q.count(arr[i]) ? q[arr[i]] : -1), i};
			q[arr[i]] = i;
		}
		sort(all(t), greater<pii>{});
		tr.reserve(N);
		for(int i = 0; i < N; ++ i){
			while(!t.empty() && t.back().first < i){
				tr.set(tr.back(), t.back().second, 1);
				t.pop_back();
			}
			p[i] = tr.back();
		}
	}
	int query(int l, int r){
		return tr.query(p[l], l, r);
	}
	int lower_bound(int l, int k){
		return tr.lower_bound(p[l], k + tr.query(p[l], 0, l));
	}
	int upper_bound(int l, int k){
		return tr.upper_bound(p[l], k + tr.query(p[l], 0, l));
	}
};

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int n;
	cin >> n;
	vi a(n);
	cin >> a;
	distinct_value_query q(a);
	for(int k = 1; k <= n; ++ k){
		int res = 0;
		for(int i = 0; i < n; ){
			res ++;
			int j = q.upper_bound(i, k) - 1;
			i = j;
		}
		cout << res << " ";
	}
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////


#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<class L, class R>
istream &operator>>(istream &in, pair<L, R> &arr){
    return in >> arr.first >> arr.second;
}
template<class ...Args, template<class...> class T>
istream &operator>>(enable_if_t<!is_same_v<T<Args...>, string>, istream> &in, T<Args...> &arr){
	for(auto &x: arr) in >> x; return in;
}
template<class L, class R>
ostream &operator<<(ostream &out, const pair<L, R> &arr){
    return out << "(" << arr.first << ", " << arr.second << ") ";
}
template<class ...Args, template<class...> class T>
ostream &operator<<(enable_if_t<!is_same_v<T<Args...>, string>, ostream> &out, const T<Args...> &arr){
	for(auto &x: arr) out << x << " "; return out << "\n";
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define all(a) a.begin(), a.end()
#define sz(a) (int)a.size()
typedef long long ll;
typedef vector<int> vi; typedef vector<ll> vl; typedef vector<double> vd; typedef vector<string> vs;
typedef pair<int, int> pii; typedef pair<ll, ll> pll; typedef pair<int, ll> pil; typedef pair<ll, int> pli;
typedef vector<pii> vpii; typedef vector<pil> vpil; typedef vector<pli> vpli; typedef vector<pll> vpll;
template<class T>
using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef tuple<int, int, int> tpl; typedef vector<tpl> vtpl;

template<class T>
struct node{
	node *l = 0, *r = 0;
	T val;
	node(T val): val(val){}
	node(node *l, node *r, function<T(T, T)> bin_op, T id): l(l), r(r), val(id){
		if(l) val = bin_op(l->val, val);
		if(r) val = bin_op(val, r->val);
	}
};
template<class T, class BO>
struct persistent_segment: vector<node<T> *>{
	int N;
	BO bin_op;
	const T id;
	persistent_segment(const vector<T> &arr, BO bin_op, T id): N(arr.size()), bin_op(bin_op), id(id){
		this->push_back(build(arr, 0, N));
	}
	node<T> *build(const vector<T> &arr, int left, int right){
		if(left + 1 == right) return new node<T>(arr[left]);
		int mid = left + right >> 1;
		return new node<T>(build(arr, left, mid), build(arr, mid, right), bin_op, id);
	}
	T pq(node<T> *u, int left, int right, int ql, int qr){
		if(qr <= left || right <= ql) return id;
		if(ql <= left && right <= qr) return u->val;
		int mid = left + right >> 1;
		return bin_op(pq(u->l, left, mid, ql, qr), pq(u->r, mid, right, ql, qr));
	}
	T query(node<T> *u, int ql, int qr){
		return pq(u, 0, N, ql, qr);
	}
	node<T> *ps(node<T> *u, int left, int right, int p, int val){
		if(left + 1 == right) return new node<T>(val);
		int mid = left + right >> 1;
		if(mid > p) return new node<T>(ps(u->l, left, mid, p, val), u->r, bin_op, id);
		else return new node<T>(u->l, ps(u->r, mid, right, p, val), bin_op, id);
	}
	void set(node<T> *u, int p, int val){
		this->push_back(ps(u, 0, N, p, val));
	}
};
template<class T>
struct distinct_value_query{
	int N;
	vector<node<T> *> p;
	persistent_segment<int, plus<int>> tr;
	distinct_value_query(const vector<T> &arr): N(sz(arr)), p(N), tr(vi(N), plus<int>{}, 0){
		map<T, int> q;
		vpii t;
		for(int i = 0; i < N; ++ i){
			t.emplace_back((q.count(arr[i]) ? q[arr[i]] : -1), i);
			q[arr[i]] = i;
		}
		sort(all(t), greater<pii>{});
		tr.reserve(N);
		for(int i = 0; i < N; ++ i){
			while(!t.empty() && t.back().first < i){
				tr.set(tr.back(), t.back().second, 1);
				t.pop_back();
			}
			p[i] = tr.back();
		}
	}
	int query(int l, int r){
		return tr.query(p[l], l, r);
	}
};

template<class Pred>
ll custom_binary_search(ll low, ll high, Pred p, bool is_left = true){
	assert(low < high);
	if(is_left){
		while(high - low > 1){
			ll mid = low + (high - low >> 1);
			p(mid) ? low = mid : high = mid;
		}
		return low;
	}
	else{
		while(high - low > 1){
			ll mid = low + (high - low >> 1);
			p(mid) ? high = mid : low = mid;
		}
		return high;
	}
}

int main(){
	cin.tie(0)->sync_with_stdio(0);
	int n;
	cin >> n;
	vi a(n);
	cin >> a;
	distinct_value_query q(a);
	for(int k = 1; k <= n; ++ k){
		int res = 0;
		for(int i = 0; i < n; ){
			res ++;
			int j = custom_binary_search(min(i + k, n), n + 1, [&](int x){return q.query(i, x) <= k;});
			i = j;
		}
		cout << res << " ";
	}
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                //
//                                   Coded by Aeren                                   //
//                                                                                //
////////////////////////////////////////////////////////////////////////////////////////


#include<bits/stdc++.h>
using namespace std;
typedef int ll;
ifstream fin("AAtest.in.txt");
struct puu{
    ll su,k;
    puu *l,*r;
};
ll n,a[100005],varv[100005],vas,koh;
puu *p[200005];

puu *teepuu(ll l,ll r){
    puu *pp=new(puu);
    pp->su=0;
    if(l==r){
        pp->k=l;
        pp->l=0;
        pp->r=0;
    }
    else{
        ll k=(l+r)/2;
        pp->k=k;
        pp->l=teepuu(l,k);
        pp->r=teepuu(k+1,r);
    }
    return pp;
}

void pane(puu *p1,puu *p2,ll k,ll v){
    if(p1->l){
        puu *pp=new(puu);
        if(k<=p1->k){
            pp->k=p1->l->k;
            pp->su=p1->l->su;
            pp->l=p1->l->l;
            pp->r=p1->l->r;
            p2->l=pp;
            pane(p1->l,pp,k,v);
        }
        else{
            pp->k=p1->r->k;
            pp->su=p1->r->su;
            pp->l=p1->r->l;
            pp->r=p1->r->r;
            p2->r=pp;
            pane(p1->r,pp,k,v);
        }
        p2->su=p2->l->su+p2->r->su;
    }
    else p2->su=v;
}

ll otsi(puu *pp,ll su){
    if(!pp->l) return pp->k;
    if(pp->r->su>=su) return otsi(pp->r,su);
    else return otsi(pp->l,su-pp->r->su);
}

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
    cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];
    p[0]=teepuu(1,n);
    memset(varv,-1,sizeof(varv));
    ll x,y;
    for(int i=1; i<=n; i++){
        x=2*i-1; y=2*i;
        if(varv[a[i]]!=-1){
            p[x]=new(puu);
            p[x]->k=p[x-1]->k;
            p[x]->su=p[x-1]->su;
            p[x]->l=p[x-1]->l;
            p[x]->r=p[x-1]->r;
            pane(p[x-1],p[x],varv[a[i]],0);
        }
        else p[i*2-1]=p[2*i-2];
        varv[a[i]]=i;
        p[y]=new(puu);
        p[y]->k=p[x]->k;
        p[y]->su=p[x]->su;
        p[y]->l=p[x]->l;
        p[y]->r=p[x]->r;
        pane(p[x],p[y],varv[a[i]],1);
    }
    for(int k=1; k<=n; k++){
        vas=1;
        koh=n;
        while(koh>=1){
            if(p[koh*2]->su<=k) break;
            koh=otsi(p[koh*2],k+1);
            vas++;
        }
        cout<<vas<<" ";
    }
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ifstream fin("AAtest.in.txt");
struct puu{
    ll su,k;
    puu *l,*r;
};
ll n,a[100005],varv[100005],vas,koh;
puu *p[200005];

puu *teepuu(ll l,ll r){
    puu *pp=new(puu);
    pp->su=0;
    if(l==r){
        pp->k=l;
        pp->l=0;
        pp->r=0;
    }
    else{
        ll k=(l+r)/2;
        pp->k=k;
        pp->l=teepuu(l,k);
        pp->r=teepuu(k+1,r);
    }
    return pp;
}

void pane(puu *p1,puu *p2,ll k,ll v){
    if(p1->l){
        puu *pp=new(puu);
        if(k<=p1->k){
            pp->k=p1->l->k;
            pp->su=p1->l->su;
            pp->l=p1->l->l;
            pp->r=p1->l->r;
            p2->l=pp;
            pane(p1->l,pp,k,v);
        }
        else{
            pp->k=p1->r->k;
            pp->su=p1->r->su;
            pp->l=p1->r->l;
            pp->r=p1->r->r;
            p2->r=pp;
            pane(p1->r,pp,k,v);
        }
        p2->su=p2->l->su+p2->r->su;
    }
    else p2->su=v;
}

ll otsi(puu *pp,ll su){
    if(!pp->l) return pp->k;
    if(pp->r->su>=su) return otsi(pp->r,su);
    else return otsi(pp->l,su-pp->r->su);
}

int main(){
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cerr.tie(0);
    cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];
    p[0]=teepuu(1,n);
    memset(varv,-1,sizeof(varv));
    ll x,y;
    for(int i=1; i<=n; i++){
        x=2*i-1; y=2*i;
        if(varv[a[i]]!=-1){
            p[x]=new(puu);
            p[x]->k=p[x-1]->k;
            p[x]->su=p[x-1]->su;
            p[x]->l=p[x-1]->l;
            p[x]->r=p[x-1]->r;
            pane(p[x-1],p[x],varv[a[i]],0);
        }
        else p[i*2-1]=p[2*i-2];
        varv[a[i]]=i;
        p[y]=new(puu);
        p[y]->k=p[x]->k;
        p[y]->su=p[x]->su;
        p[y]->l=p[x]->l;
        p[y]->r=p[x]->r;
        pane(p[x],p[y],varv[a[i]],1);
    }
    for(int k=1; k<=n; k++){
        vas=1;
        koh=n;
        while(koh>=1){
            if(p[koh*2]->su<=k) break;
            koh=otsi(p[koh*2],k+1);
            vas++;
        }
        cout<<vas<<" ";
    }
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int &cnt, int v = 1, int l = 0, int r = max_n - 1) {
    if (r < left) return -1;

    int num = r - l + 1 - sum[v];

    if (l >= l && num <= cnt) {
        cnt -= num;
        return r;
    }

    if (l == r) {
        cnt -= num;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(left, cnt, v * 2, l, m);

    if (cnt >= 0)
        r2 = get(left, cnt, v * 2 + 1, m + 1, r);

    return max(r1, r2);

}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
        upd(i, 1, 0, max_n, 1);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int left, int &cnt, int v = 1, int l = 0, int r = max_n - 1) {
    if (r < left) return -1;

    int num = r - l + 1 - sum[v];

    if (l >= left && num <= cnt) {
        cnt -= num;
        return r;
    }

    if (l == r) {
        cnt -= num;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(left, cnt, v * 2, l, m);

    if (cnt >= 0)
        r2 = get(left, cnt, v * 2 + 1, m + 1, r);

    return max(r1, r2);

}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(i, cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int left, int &cnt, int v = 1, int l = 0, int r = max_n - 1) {
    if (r < left) return -1;

    int num = r - l + 1 - sum[v];
    //cout << l << " " << r << " " << sum[v] << " " << cnt << endl;

    if (num <= cnt && left <= l) {
        cnt -= num;
        //cout << cnt << " " << r << endl;
        if (cnt == 0) return r;
        else return -1;
    }
    if (l == r) {
        cnt = -1;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(left, cnt, v * 2, l, m);

    if (cnt != -1)
        r2 = get(left, cnt, v * 2 + 1, m + 1, r);

    if (r2 == -1) return r1;
    return r2;
}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);

    cout << sum[1] << endl;
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(i, cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int left, int &cnt, int v = 1, int l = 0, int r = max_n - 1) {
    if (r < left) return -1;

    int num = r - l + 1 - sum[v];
    //cout << l << " " << r << " " << sum[v] << " " << cnt << endl;

    if (num <= cnt && left <= l) {
        cnt -= num;
        //cout << cnt << " " << r << endl;
        if (cnt == 0) return r;
        else return -1;
    }
    if (l == r) {
        cnt = -1;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(left, cnt, v * 2, l, m);

    if (cnt != -1)
        r2 = get(left, cnt, v * 2 + 1, m + 1, r);

    if (r2 == -1) return r1;
    return r2;
}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(i, cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int &cnt, int v = 1, int l = 0, int r = max_n - 1) {

    int num = r - l + 1 - sum[v];

    if (num <= cnt) {
        cnt -= num;
        return r;
    }

    if (l == r) {
        cnt -= num;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(cnt, v * 2, l, m);

    if (cnt >= 0)
        r2 = get(cnt, v * 2 + 1, m + 1, r);

    return max(r1, r2);

}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
        upd(i, 1, 0, max_n, 1);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>

using namespace std;

#define aidar asadulin

#define int long long
#define ll long long
#define mp make_pair
#define pii pair<int, int>
#define fi first
#define se second
#define all(_v) _v.begin(), _v.end()
#define sz(a) (int) (a.size())
#define chkmax(a, b) a = max(a, b)
#define chkmin(a, b) a = min(a, b)
#define ld long double

const int inf = 1e15;
const int max_n = (1 << 17);

int sum[2 * max_n];

void upd(int id, int v = 1, int l = 0, int r = max_n - 1, int num = 0) {
    if (l > id || r < id) return;
    if (l == id && r == id) {
        sum[v] = num;
        return;
    }
    int m = (l + r) / 2;
    upd(id, v * 2, l, m, num);
    upd(id, v * 2 + 1, m + 1, r, num);
    sum[v] = sum[v * 2] + sum[v * 2 + 1];
}

void build(vector<int> a) {
    for(int i = 0;i < sz(a);i++) {
        upd(i, 1, 0, max_n - 1, a[i]);
    }
}

int get(int left, int &cnt, int v = 1, int l = 0, int r = max_n - 1) {
    if (r < left) return -1;

    int num = r - l + 1 - sum[v];

    if (l >= l && num <= cnt) {
        cnt -= num;
        return r;
    }

    if (l == r) {
        cnt -= num;
        return -1;
    }

    int m = (l + r) / 2;

    int r1, r2 = -1;
    r1 = get(left, cnt, v * 2, l, m);

    if (cnt >= 0)
        r2 = get(left, cnt, v * 2 + 1, m + 1, r);

    return max(r1, r2);

}

void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i++)
        cin >> a[i];

    vector<int> last(n + 1, inf);
    vector<int> nxt(n);
    vector<int> temp(n);
    for(int i = n - 1;i >= 0;i--) {
        nxt[i] = last[a[i]];
        last[a[i]] = i;
    }
    for(int i = 0;i < n;i++) {
        if (nxt[i] < n) temp[nxt[i]] = 1;
    }

    //cout << "bef build" << endl;

    build(temp);
    //cout << "after build" << endl;

    vector<deque<pii>> req(n + 1);

    for(int i = n;i >= 1;i--)
        req[0].emplace_back(i, 0);

    for(int i = 0;i < n;i++) {
        while(sz(req[i])) {
            pii v = req[i].back();
            req[i].pop_back();
            v.se++;

            int cnt = v.fi;

            //cout << "bef " << i << " " << v.fi << endl;
            int temp = get(i, cnt) + 1;
            req[min(n, temp)].emplace_back(v);

            //cout << i << " " << v.fi << " " << temp << endl;
            //cout << "aft " << i << " " << v.fi << endl;
        }

        if (nxt[i] < n) upd(nxt[i]);
    }

    vector<int> res(n);
    for(auto i : req[n]) {
        res[i.fi - 1] = i.se;
    }

    for(int i : res)
        cout << i << " ";
}

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

    solve();
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

int naive(int mid)
{
    unordered_set<int,int> mp;
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp.insert(vec[i]);
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp.insert(vec[i]);
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

unordered_set<int> mp;
int naive(int mid)
{
    mp.clear();
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp.insert(vec[i]);
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp.insert(vec[i]);
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

unordered_set<int> mp;
int naive(int mid)
{
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp.insert(vec[i]);
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp.insert(vec[i]);
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}
vector<vector<int> > sets;
int ind=-1;
int naive(int mid)
{
    sets.resize(sets.size()+1,vector<int>(100003));
    ind++;
    int res=0;
    int currcnt=0;
    for(int i=0;i<n;i++)
    {
        if(sets[ind][vec[i]]==0)
        {
            sets[ind][vec[i]]=1;
            currcnt++;
        }
        if(currcnt>mid)
        {
            currcnt=1;
            res++;
            sets.resize(sets.size()+1,vector<int>(100003));
            ind++;
            sets[ind][vec[i]]=1;
        }
    }
    if(currcnt)
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

int naive(int mid)
{
    unordered_map<int,int> mp;
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp[vec[i]]=1;
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp[vec[i]]=1;
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}
vector<int> sets;
int naive(int mid)
{
    int res=0;
    int currcnt=0;
    vector<int> used;
    for(int i=0;i<n;i++)
    {
        if(sets[vec[i]]==0)
        {
            sets[vec[i]]=1;
            used.push_back(vec[i]);
            currcnt++;
        }
        if(currcnt>mid)
        {
            currcnt=1;
            res++;
            for(int j=0;j<used.size();j++)
            {
                sets[used[j]]=0;
            }
            used.clear();
            sets[vec[i]]=1;
            used.push_back(vec[i]);
        }
    }
    if(currcnt)
        res++;
    for(int i=0;i<used.size();i++)
        sets[used[i]]=0;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    sets.resize(100005);
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    faster;
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

int naive(int mid)
{
    map<int,int> mp;
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp[vec[i]]=1;
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp[vec[i]]=1;
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
#define faster ios_base::sync_with_stdio(false);cin.tie(NULL);

int n;
vector<int> vec;
vector<int> ans;
void init()
{
    cin>>n;
    vec.resize(n);
    ans.resize(n+1);
    for(int i=0;i<n;i++)
        cin>>vec[i];
}

int naive(int mid)
{
    unordered_map<int,int> mp;
    int res=0;
    for(int i=0;i<n;i++)
    {
        mp[vec[i]]=1;
        if((int)mp.size()>mid)
        {
            res++;
            mp.clear();
            mp[vec[i]]=1;
        }
    }
    if(mp.size())
        res++;
    return res;
}
void DC(int l,int r,int low,int high)
{
    if(l>r)return;
    int mid=(l+r)/2;
    if(low==high)
        ans[mid]=low;
    else
        ans[mid]=naive(mid);
    DC(l,mid-1,ans[mid],high);
    DC(mid+1,r,low,ans[mid]);
}

signed main()
{
    init();
    DC(1,n,1,n);
    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 100005, M = 8000006;

int n;
int a[N];

int z;
int ll[M], rr[M];
int t[M];

int ubd(int tl, int tr, int x, int y, int pos)
{
    int ypos = ++z;
    ll[ypos] = ll[pos];
    rr[ypos] = rr[pos];
    t[ypos] = t[pos];
    if (tl == tr)
    {
        t[ypos] = y;
        return ypos;
    }
    int m = (tl + tr) / 2;
    if (x <= m)
    {
        ll[ypos] = ubd(tl, m, x, y, ll[pos]);
    }
    else
    {
        rr[ypos] = ubd(m + 1, tr, x, y, rr[pos]);
    }
    t[ypos] = t[ll[ypos]] + t[rr[ypos]];
}

int qry(int tl, int tr, int y, int pos)
{
    if (tl == tr)
    {
        return tl;
    }
    int m = (tl + tr) / 2;
    if (t[rr[pos]] >= y)
        return qry(m + 1, tr, y, rr[pos]);
    return qry(tl, m, y - t[rr[pos]], ll[pos]);
}

int c[N];
int u[N];

void solv()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i)
    {
        if (!c[a[i]])
            u[i] = ubd(1, n, i, 1, u[i - 1]);
        else
        {
            u[i] = ubd(1, n, c[a[i]], 0, u[i - 1]);
            u[i] = ubd(1, n, i, 1, u[i]);
        }
        c[a[i]] = i;
    }
    for (int k = 1; k <= n; ++k)
    {
        int ans = 0;
        int s = n;
        while (s)
        {
            ++ans;
            if (t[u[s]] <= k)
                break;
            else
                s = qry(1, n, k + 1, u[s]);
        }
        printf("%d ", ans);
    }
    printf("\n");
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    solv();
    return 0;
}

//while ((double)clock() / CLOCKS_PER_SEC <= 0.9){}


#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 100005, M = 8000006;

int n;
int a[N];

int z;
int ll[M], rr[M];
int t[M];

int ubd(int tl, int tr, int x, int y, int pos)
{
    int ypos = ++z;
    ll[ypos] = ll[pos];
    rr[ypos] = rr[pos];
    t[ypos] = t[pos];
    if (tl == tr)
    {
        t[ypos] = y;
        return ypos;
    }
    int m = (tl + tr) / 2;
    if (x <= m)
    {
        ll[ypos] = ubd(tl, m, x, y, ll[pos]);
    }
    else
    {
        rr[ypos] = ubd(m + 1, tr, x, y, rr[pos]);
    }
    t[ypos] = t[ll[ypos]] + t[rr[ypos]];
    return ypos;
}

int qry(int tl, int tr, int y, int pos)
{
    if (tl == tr)
    {
        return tl;
    }
    int m = (tl + tr) / 2;
    if (t[rr[pos]] >= y)
        return qry(m + 1, tr, y, rr[pos]);
    return qry(tl, m, y - t[rr[pos]], ll[pos]);
}

int c[N];
int u[N];

void solv()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i)
    {
        if (!c[a[i]])
            u[i] = ubd(1, n, i, 1, u[i - 1]);
        else
        {
            u[i] = ubd(1, n, c[a[i]], 0, u[i - 1]);
            u[i] = ubd(1, n, i, 1, u[i]);
        }
        c[a[i]] = i;
    }
    for (int k = 1; k <= n; ++k)
    {
        int ans = 0;
        int s = n;
        while (s)
        {
            ++ans;
            if (t[u[s]] <= k)
                break;
            else
                s = qry(1, n, k + 1, u[s]);
        }
        printf("%d ", ans);
    }
    printf("\n");
}

int main()
{
    #ifdef SOMETHING
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    #endif // SOMETHING
    solv();
    return 0;
}

//while ((double)clock() / CLOCKS_PER_SEC <= 0.9){}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a[n];
    F0R(i,n)cin>>a[i];
    int ans;
    unordered_set<int> cols;
    int k;
    for(k=1; k*k<=n; ++k)
    {
        ans=1;
        cols.clear();
        F0R(i,n)
        {
            if(cols.find(a[i])==cols.end())
            {
                if(sz(cols)==k)
                {
                    cols.clear();
                    cols.insert(a[i]);
                    ++ans;
                }
                else
                    cols.insert(a[i]);
            }
        }
        cout<<ans<<' ';
    }
    int lef[k+2];
    int rig[k+2];
    int num_cols[k+2];
    fill(lef,lef+k+2,0);
    fill(rig,rig+k+2,-1);
    fill(num_cols,num_cols+k+2,0);
    int freq[k+2][n];
    F0R(i,k+2)fill(freq[i],freq[i]+n,0);
    for(;k<n+1;++k)
    {
        ans=0;
        for(int i=1; rig[i-1]+1<n; ++i)
        {
            while(lef[i] <= rig[i-1])
            {
                --freq[i][a[lef[i]]];
                if(freq[i][a[lef[i]]]==0)
                {
                    --num_cols[i];
                }
                ++lef[i];
            }
            while(rig[i]+1<n)
            {
                if(freq[i][a[rig[i]+1]]!=0)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                }
                else if(num_cols[i] < k)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                    ++num_cols[i];
                }
                else break;
            }
            ++ans;
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a[n];
    F0R(i,n)cin>>a[i];
    int ans;
    int owner[n];
    fill(owner,owner+n,-1);
    int k;
    int cur=0;
    int siz;
    for(k=1; k*k<=n; ++k)
    {
        ans=1;
        ++cur;
        siz=0;
        F0R(i,n)
        {
            if(owner[a[i]]!=cur)
            {
                if(siz==k)
                {
                    siz=0;
                    ++cur;
                    ++ans;
                }
                ++siz;
                owner[a[i]]=cur;
            }
        }
        cout<<ans<<' ';
    }
    int lef[k+2];
    int rig[k+2];
    int num_cols[k+2];
    fill(lef,lef+k+2,0);
    fill(rig,rig+k+2,-1);
    fill(num_cols,num_cols+k+2,0);
    int freq[k+2][n];
    F0R(i,k+2)fill(freq[i],freq[i]+n,0);
    for(;k<n+1;++k)
    {
        ans=0;
        for(int i=1; rig[i-1]+1<n; ++i)
        {
            while(lef[i] <= rig[i-1])
            {
                --freq[i][a[lef[i]]];
                if(freq[i][a[lef[i]]]==0)
                {
                    --num_cols[i];
                }
                ++lef[i];
            }
            while(rig[i]+1<n)
            {
                if(freq[i][a[rig[i]+1]]!=0)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                }
                else if(num_cols[i] < k)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                    ++num_cols[i];
                }
                else break;
            }
            ++ans;
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

//int const N=1e5;
//int step[N];
//int cur_step=0;
//int solve(int k)
//{
//	int on=0;
//	int ans=0;
//	while(on<n)
//	{
//		cur_step++;
//		int got=0;
//		while(on<n)
//		{
//			if(step[a[on]]!=cur_step)
//				got++;
//			step[a[on]] = cur_step;
//			if(got>k)
//				break;
//			on++;
//		}
//
//		ans++;
//	}
//	return ans;
//}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a[n];
    vector<deque<int>> cur;
    vector<map<int,int>> sum;
    F0R(i,n)
    {
        cin>>a[i];
        if(cur.empty()||cur.back().back()!=a[i])
        {
            cur.pb(deque<int> {a[i]});
            sum.pb(map<int,int> {{a[i],1}});
        }
    }
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    int sqrtn = sqrt(n);
    int owner[n];
    fill(owner,owner+n,-1);
    int id=0;
    int siz;
    FOR(k,1,sqrtn)
    {
        ans=1;
        ++id;
        siz=0;
        F0R(i,n)
        {
            if(owner[a[i]]!=id)
            {
                if(siz==k)
                {
                    siz=0;
                    ++id;
                    ++ans;
                }
                ++siz;
                owner[a[i]]=id;
            }
        }
        cout<<ans<<' ';
    }
    FOR(k,sqrtn,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = sz(sum[now])<k;
                if(ok1||ok2)
                {
                    if(!ok1)
                    {
                        sum[now].insert({col, 1});
                    }
                    else ++sum[now][col];
                    --sum[nxt][col];
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt][col]==0)
                    {
                        sum[nxt].erase(col);
                    }
                    if(sum[nxt].empty())suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a[n];
    F0R(i,n)cin>>a[i];
    int ans;
    set<int> cols;
    int k;
    for(k=1; k*k<=n; ++k)
    {
        ans=1;
        cols.clear();
        F0R(i,n)
        {
            if(cols.find(a[i])==cols.end())
            {
                if(sz(cols)==k)
                {
                    cols.clear();
                    cols.insert(a[i]);
                    ++ans;
                }
                else
                    cols.insert(a[i]);
            }
        }
        cout<<ans<<' ';
    }
    int lef[k+2];
    int rig[k+2];
    int num_cols[k+2];
    fill(lef,lef+k+2,0);
    fill(rig,rig+k+2,-1);
    fill(num_cols,num_cols+k+2,0);
    int freq[k+2][n];
    F0R(i,k+2)fill(freq[i],freq[i]+n,0);
    for(;k<n+1;++k)
    {
        ans=0;
        for(int i=1; rig[i-1]+1<n; ++i)
        {
            while(lef[i] <= rig[i-1])
            {
                --freq[i][a[lef[i]]];
                if(freq[i][a[lef[i]]]==0)
                {
                    --num_cols[i];
                }
                ++lef[i];
            }
            while(rig[i]+1<n)
            {
                if(freq[i][a[rig[i]+1]]!=0)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                }
                else if(num_cols[i] < k)
                {
                    ++freq[i][a[rig[i]+1]];
                    ++rig[i];
                    ++num_cols[i];
                }
                else break;
            }
            ++ans;
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a;
    vector<deque<int>> cur;
    vector<map<int,int>> sum;
    F0R(i,n)
    {
        cin>>a;
        if(cur.empty()||cur.back().front()!=a)
        {
            cur.pb(deque<int> {a});
            sum.pb(map<int,int> ());
            sum.back().insert({a,1});
        }
        else ++sum.back()[a];
    }
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    int cols[n];
    fill(cols,cols+n,1);
    FOR(k,1,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = cols[now]<k;
                if(ok1||ok2)
                {
                    if(!ok1)
                    {
                        ++cols[now];
                        sum[now].insert({col, 1});
                    }
                    else ++sum[now][col];
                    --sum[nxt][col];
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt][col]==0)
                    {
                        --cols[nxt];
                        sum[nxt].erase(col);
                    }
                    if(cols[nxt]==0)suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a;
    vector<deque<int>> cur;
    F0R(i,n)
    {
        cin>>a;
        if(cur.empty()||cur.back().front()!=a)
        {
            cur.pb(deque<int> {a});
        }
    }
    vector<map<int,int>> sum;
    sum.rsz(sz(cur));
    F0R(i,sz(cur))
    {
        sum[i].insert({cur[i].back(),1});
    }
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    int cols[n];
    fill(cols,cols+n,1);
    FOR(k,1,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            cols[now]=cols[now];
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = cols[now]<k;
                if(ok1||ok2)
                {
                    if(!ok1)
                    {
                        ++cols[now];
                        sum[now].insert({col, 1});
                    }
                    else ++sum[now][col];
                    --sum[nxt][col];
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt][col]==0)--cols[nxt];
                    if(cols[nxt]==0)suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

//int const N=1e5;
//int step[N];
//int cur_step=0;
//int solve(int k)
//{
//	int on=0;
//	int ans=0;
//	while(on<n)
//	{
//		cur_step++;
//		int got=0;
//		while(on<n)
//		{
//			if(step[a[on]]!=cur_step)
//				got++;
//			step[a[on]] = cur_step;
//			if(got>k)
//				break;
//			on++;
//		}
//
//		ans++;
//	}
//	return ans;
//}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a;
    vector<deque<int>> cur;
    vector<map<int,int>> sum;
    F0R(i,n)
    {
        cin>>a;
        if(cur.empty()||cur.back().back()!=a)
        {
            cur.pb(deque<int> {a});
            sum.pb(map<int,int> {{a,1}});
        }
    }
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    int sqrtn = sqrt(n);
    set<int> cols;
    FOR(k,1,sqrtn)
    {
        ans=1;
        cols.clear();
        F0R(i,sz(cur))
        {
            if(sz(cols)<k||cols.find(cur[i].back())!=cols.end())
            {
                cols.insert(cur[i].back());
            }
            else
            {
                ++ans;
                cols.clear();
                cols.insert(cur[i].back());
            }
        }
        cout<<ans<<' ';
    }
    FOR(k,sqrtn,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = sz(sum[now])<k;
                if(ok1||ok2)
                {
                    if(!ok1)
                    {
                        sum[now].insert({col, 1});
                    }
                    else ++sum[now][col];
                    --sum[nxt][col];
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt][col]==0)
                    {
                        sum[nxt].erase(col);
                    }
                    if(sum[nxt].empty())suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a;
    vector<deque<int>> cur;
    F0R(i,n)
    {
        cin>>a;
        if(cur.empty()||cur.back().front()!=a)
        {
            cur.pb(deque<int> {a});
        }
    }
    vector<multiset<int>> sum;
    sum.rsz(sz(cur));
    F0R(i,sz(cur))sum[i].insert(cur[i].back());
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    int cols[n];
    fill(cols,cols+n,1);
    FOR(k,1,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            cols[now]=cols[now];
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = cols[now]<k;
                if(ok1||ok2)
                {
                    if(!ok1)++cols[now];
                    sum[now].insert(col);
                    sum[nxt].erase(sum[nxt].find(col),++sum[nxt].find(col));
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt].find(col)==sum[nxt].end())--cols[nxt];
                    if(cur[nxt].empty())suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pair<int,int>> vpi;

#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)

#define pb push_back
#define rsz resize
#define sz(x) int(x.size())
#define all(x) begin(x), end(x)
#define f first
#define s second

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    int n;
    cin>>n;
    int a;
    vector<deque<int>> cur;
    vector<map<int,int>> sum;
    F0R(i,n)
    {
        cin>>a;
        if(cur.empty()||cur.back().back()!=a)
        {
            cur.pb(deque<int> {a});
            sum.pb(map<int,int> {{a,1}});
        }
    }
    int suc[sz(cur)];
    F0R(i,sz(cur))suc[i]=i+1;
    suc[sz(cur)-1]=-1;
    int col;
    bool ok1,ok2;
    int ans;
    int now;
    int nxt;
    FOR(k,1,n+1)
    {
        ans=0;
        now=0;
        while(now!=-1)
        {
            ++ans;
            while(suc[now]!=-1)
            {
                nxt = suc[now];
                col = cur[nxt].front();
                ok1 = sum[now].find(col)!=sum[now].end();
                ok2 = sz(sum[now])<k;
                if(ok1||ok2)
                {
                    if(!ok1)
                    {
                        sum[now].insert({col, 1});
                    }
                    else ++sum[now][col];
                    --sum[nxt][col];
                    cur[now].pb(cur[nxt].front());
                    cur[nxt].pop_front();
                    if(sum[nxt][col]==0)
                    {
                        sum[nxt].erase(col);
                    }
                    if(sum[nxt].empty())suc[now]=suc[nxt];
                }
                else break;
            }
            now=suc[now];
        }
        cout<<ans<<' ';
    }
    cout<<'\n';
    return 0;
}


#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, 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;
                int res = mid - now - mat.rangefreq(now,mid,now,mid) - i;
                if(res > 0){
                    r = mid - (res-1);
                }
                else l = mid - res;
            }
            cnt++;
            now = l;
        }
        io.write(cnt, " \n"[i == n]);
    }
}