#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
int n,a[maxn],res[maxn],vis[maxn];

int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

void solve(int l,int r,int a,int b){
	if(a==b)REP(i,l,r+1)res[i]=a;
	else if(l==r)res[r]=calc(r);
	else{
		int mid=(l+r)/2,tt=calc(mid);
		solve(l,mid,a,tt),solve(mid+1,r,tt+1,b);
	}
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	solve(1,n,n,1);
	REP(i,1,n+1)cout<<res[i]<<" ";cout<<endl;
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=78;
int n,flag=1,a[maxn];
bool vis[maxn];

inline int calc(int x){
	int ret=0,cnt=0;
	++flag;
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i];
	int x=n,k=1;
	while(x>=limit)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k-1,r=n+1;
		while(l+1<r){
			int mid=(l+r)/2;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(l==k-1)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		//if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
int n,a[maxn],res[maxn],vis[maxn];

int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

void solve(int l,int r,int a,int b){
	if(a+1==b)RREP(i,r,l)res[i]=b;
	else if(l+1==r)res[r]=calc(r);
	else{
		int mid=(l+r)/2,tt=calc(mid);
		solve(l,mid,a,tt),solve(mid,r,tt,b);
	}
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	solve(0,n,0,n);
	REP(i,1,n+1)cout<<res[i]<<" ";cout<<endl;
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
int n,a[maxn],res[maxn],vis[maxn];

int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

void solve(int l,int r,int a,int b){
	if(a+1==b)RREP(i,r,l)res[i]=b;
	else if(l+1==r)res[r]=calc(r);
	else{
		int mid=(l+r)/2,tt=calc(mid);
		solve(l,mid,a,tt),solve(mid,r,tt,b);
	}
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	solve(0,n,0,n);
	REP(i,1,n+1)cout<<calc(i)<<" ";//cout<<res[i]<<" ";cout<<endl;
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
#pragma GCC optimize(2)
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(register int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=68;
int n,flag=0,a[maxn],vis[maxn]={};

inline int calc(int x){
	register int ret=0,cnt=0;
	++flag;
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=cnt+1,vis[a[i]]=flag;
		if(cnt>=x)cnt-=x;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i];
	int x=n,k=1;
	while(x>=limit)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k-1,r=n+1;
		while(l+1<r){
			int mid=l+r>>1;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(l==k-1)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		//if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
#pragma GCC optimize(2)
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(register int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=20;
int n,flag=0,a[maxn],vis[maxn]={};

inline int calc(int x){
	register int ret=0,cnt=0;
	++flag;
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=cnt+1,vis[a[i]]=flag;
		if(cnt>=x)cnt-=x;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i];
	int x=n,k=1;
	while(x>=limit)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k-1,r=n+1;
		while(l+1<r){
			int mid=l+r>>1;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(l==k-1)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		//if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
int n,a[maxn],res[maxn],vis[maxn];

int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

void solve(int l,int r,int a,int b){
	if(a+1==b)RREP(i,r,l)res[i]=b;
	else if(l+1==r)res[r]=calc(r);
	else{
		int mid=(l+r)/2,tt=calc(mid);
		solve(l,mid,tt,b),solve(mid,r,a,tt);
	}
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	solve(0,n,0,n);
	REP(i,1,n+1)cout<<res[i]<<" ";cout<<endl;
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=80;
int n,a[maxn],vis[maxn];

inline int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	int x=n,k=1;
	while(x>=limit&&k<n)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k,r=n+1;
		while(l+1<r){
			int mid=(l+r)/2;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(calc(l)<i)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		if(clock()*10>19*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=200;
int n,a[maxn],vis[maxn];

inline int calc(int x){
	int ret=0,cnt=0,flag=1;
	MST(vis,0);
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=(cnt+1)%x,vis[a[i]]=flag;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i],--a[i];
	int x=n,k=1;
	while(x>=limit&&k<n)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k,r=n+1;
		while(l+1<r){
			int mid=(l+r)/2;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(calc(l)<i)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
#pragma GCC optimize(2)
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(register int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=25;
int n,flag=0,a[maxn],vis[maxn]={};

inline int calc(int x){
	register int ret=0,cnt=0;
	++flag;
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=cnt+1,vis[a[i]]=flag;
		if(cnt>=x)cnt-=x;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i];
	int x=n,k=1;
	while(x>=limit)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k-1,r=n+1;
		while(l+1<r){
			int mid=l+r>>1;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(l==k-1)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		//if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
#include<stdint.h>
#define int int_fast64_t
#pragma GCC optimize(2)
using namespace std;
typedef pair<int,int> pii;
typedef vector<int> VI;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))
#define RREP(i,j,k) for(register int (i)=(j)-1;(i)>=(k);--(i))
#define ALL(a) (a).begin(),(a).end()
#define MST(a,v) memset((a),(v),sizeof(a))
#define pb push_back
#define F first
#define S second
#define endl '\n'
//																#define __debug
#ifdef __debug
	#define IOS (void)0
	#define de(...) cout<<__VA_ARGS__
	#define ar(a,s,t) {REP(__i,s,t)de((a)[__i]<<' ');de(endl);}
#else
	#define IOS cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false)
	#define de(...) (void)0
	#define ar(...) (void)0
#endif

const int maxn=1e5+9;
const int limit=50;
int n,flag=0,a[maxn],vis[maxn]={};

inline int calc(int x){
	register int ret=0,cnt=0;
	++flag;
	REP(i,0,n)if(vis[a[i]]!=flag){
		if(!cnt)++ret,++flag;
		cnt=cnt+1,vis[a[i]]=flag;
		if(cnt>=x)cnt-=x;
	}
	return ret;
}

main(){
	IOS;
	cin>>n;
	REP(i,0,n)cin>>a[i];
	int x=n,k=1;
	while(x>=limit)cout<<(x=calc(k++))<<" ";
	RREP(i,limit,1){
		int l=k-1,r=n+1;
		while(l+1<r){
			int mid=l+r>>1;
			if(calc(mid)<i)r=mid;
			else l=mid;
		}
		if(l==k-1)continue;
		while(k<=l){
			cout<<i<<" ";
			++k;
		}
		//if(clock()*100>199*CLOCKS_PER_SEC)break;
	}
}


#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n,A[N],st[N],Ans[N];
vector<int>B[N],C[N];
struct Binary_Indexed_Tree{
	int bit[N];
	void Add(int i,int x){
		while (i<=n){
			bit[i]+=x;
			i+=i&-i;
		}
	}
	int Query(int x){
		int i,res=0;
		for (i=16;i>=0;i--){
			int t=res|(1<<i);
			if (t<=n && x-bit[t]>=0){
				res=t;
				x-=bit[t];
			}
		}
		return res;
	}
}BIT;
void Deal(int x){
	if (st[x]<(int)B[x].size()){
		BIT.Add(B[x][st[x]++],1);
	}
}
int main(){
	int i,j;
	scanf("%d",&n);
	for (i=1;i<=n;i++){
		scanf("%d",&A[i]);
		B[A[i]].push_back(i);
		C[1].push_back(i);
	}
	for (i=1;i<=n;i++){
		Deal(i);
	}
	for (i=1;i<=n;i++){
		for (j=0;j<(int)C[i].size();j++){
			int x=C[i][j];
			int R=BIT.Query(x);
			Ans[x]++;
			C[R+1].push_back(x);
		}
		BIT.Add(i,-1);
		Deal(A[i]);
	}
	for (i=1;i<=n;i++){
		printf("%d%c",Ans[i]," \n"[i==n]);
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int c[100007];
int vis[100007];
int ans[100007];
int n;
int get_cnt(int k)
{
    int res=0,cnt=0;
    memset(vis,-1,sizeof(vis));
    for(int i=1; i<=n; i++)
    {
        if(vis[c[i]]==res) continue;
        vis[c[i]]=res;
        cnt++;
        if(cnt>k)
        {
            res++;
            cnt=1;
            vis[c[i]]=res;
        }
    }
    return res+1;
}

void solve(int l,int r)
{
    if(l>r) return ;
    int cntl=get_cnt(l);
    int cntr=get_cnt(r);
    if(cntl==cntr)
    {
        for(int i=l; i<=r; i++)
            ans[i]=cntl;
        return ;
    }
    ans[l]=cntl;
    ans[r]=cntr;
    int mid=(l+r)>>1;
    solve(l+1,mid);
    solve(mid+1,r-1);
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&c[i]);
    solve(1,n);
    for(int i=1; i<=n; i++)
        printf("%d ",ans[i]);
    return 0;
}


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

#define maxn 100010

int n, ans[maxn], a[maxn], vis[maxn];

void solve(int l) {
  int cnt = -1, idx = 1;
  fill(vis, vis + n + 1, 0);
  for (int i = 0; i < n; i++) if (vis[a[i]] < idx) {
    cnt++;
    if (cnt > l) {
      cnt = 0;
      idx++;
    }
    vis[a[i]] = idx;
  }
  ans[l] = idx;
}

void solve(int l, int r) {
  if (l == r - 1) solve(l);
  if (l >= r - 1) return;
  solve(l);
  solve(r - 1);
  if (ans[l] == ans[r - 1]) {
    fill(ans + l + 1, ans + r, ans[l]);
    return;
  }
  int m = (l + r) / 2;
  solve(l, m);
  solve(m, r);
}

int main() {
  cin >> n;
  for (int i = 0; i < n; i++) scanf("%d", a + i);
  solve(0, n);
  for (int i = 0; i < n; i++) printf("%d ", ans[i]);
  return 0;
}


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

#define maxn 100010

int n, ans[maxn], a[maxn], vis[maxn];

void solve(int l) {
  int cnt = -1, idx = 1;
  fill(vis, vis + n + 1, 0);
  for (int i = 0; i < n; i++) if (vis[a[i]] < idx) {
    cnt++;
    if (cnt > l) {
      cnt = 0;
      idx++;
    }
    vis[a[i]] = idx;
  }
  ans[l] = idx;
}

void solve(int l, int r) {
  if (l == r - 1) solve(l);
  if (l >= r - 1) return;
  solve(l++);
  solve(--r);
  if (ans[l - 1] == ans[r]) fill(ans + l, ans + r, ans[r]);
  int m = (l + r) / 2;
  solve(l, m);
  solve(m, r);
}

int main() {
  cin >> n;
  for (int i = 0; i < n; i++) scanf("%d", a + i);
  solve(0, n);
  for (int i = 0; i < n; i++) printf("%d ", ans[i]);
  return 0;
}


/* ****TCIITB**** */

#include<bits/stdc++.h>
#define io          ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll          int
#define pb          push_back
#define	endl		'\n'
#define pii         pair<int,int>
#define vi          vector<int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (int)x.size()
#define hell        1000000007
#define rep(i,a,b)	for(int i=a;i<b;i++)
#define lbnd        lower_bound
#define ubnd        upper_bound
#define bs          binary_search
#define mp          make_pair
#define time        cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
using namespace std;

#define N  100005
ll n;
std::vector<ll> a(N);
ll res[N];
void dnc(ll l,ll r,ll sval,ll eval)
{
	if(l>r)
		return;
	ll mid=(l+r)/2;
	if(sval==eval)
	{
		rep(i,l,r+1)
		{
			res[i]=sval;
		}
		return ;
	}
	ll cres=1;
	set<ll> curr;
	rep(i,0,n)
	{
		curr.insert(a[i]);
		if(curr.size()>mid)
		{
			cres++;
			curr.clear();
			curr.insert(a[i]);
		}
	}
	res[mid]=cres;
	dnc(l,mid-1,cres,eval);
	dnc(mid+1,r,sval,cres);

}
int main()
{

	io

	cin>>n;
	rep(i,0,n)
	{
		cin>>a[i];
	}
	dnc(0,n-1,1,n);
	res[n]=1;
	rep(i,1,n+1)
	{
		cout<<res[i]<<" ";
	}

}


/* ****TCIITB**** */

#include<bits/stdc++.h>
#define io          ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll          int
#define pb          push_back
#define	endl		'\n'
#define pii         pair<int,int>
#define vi          vector<int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (int)x.size()
#define hell        1000000007
#define rep(i,a,b)	for(int i=a;i<b;i++)
#define lbnd        lower_bound
#define ubnd        upper_bound
#define bs          binary_search
#define mp          make_pair
#define time        cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
using namespace std;

#define N  100005
ll n;
std::vector<ll> a(N);
ll res[N];
void dnc(ll l,ll r,ll sval,ll eval)
{
	if(l>r)
		return;
	ll mid=(l+r)/2;
	if(sval==eval)
	{
		rep(i,l,r+1)
		{
			res[i]=sval;
		}
		return ;
	}
	ll cres=0;
	ll cg=1;
	vector<ll> vis(n+1,0);
	rep(i,0,n)
	{
		if(vis[a[i]]!=cg)
		{
			cres++;
			vis[a[i]]=cg;
		}
		else
		{
			continue;
		}
		if(cres>mid)
		{
			cg++;
			vis[a[i]]=cg;
			cres=1;
		}
	}

	res[mid]=cg;
	dnc(l,mid-1,cg,eval);
	dnc(mid+1,r,sval,cg);

}
int main()
{

	io

	cin>>n;
	rep(i,0,n)
	{
		cin>>a[i];
	}
	dnc(0,n-1,1,n);
	res[n]=1;
	rep(i,1,n+1)
	{
		cout<<res[i]<<" ";
	}

}


/* ****TCIITB**** */

#include<bits/stdc++.h>
#define io          ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll          long long
#define pb          push_back
#define	endl		'\n'
#define pii         pair<ll int,ll int>
#define vi          vector<ll int>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (ll int)x.size()
#define hell        1000000007
#define rep(i,a,b)	for(ll int i=a;i<b;i++)
#define lbnd        lower_bound
#define ubnd        upper_bound
#define bs          binary_search
#define mp          make_pair
#define time        cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
using namespace std;

#define N  100005
ll n;
std::vector<ll> a(N);
ll res[N];
void dnc(ll l,ll r,ll sval,ll eval)
{
	if(l>r)
		return;
	ll mid=(l+r)/2;
	if(sval==eval)
	{
		rep(i,l,r+1)
		{
			res[i]=sval;
		}
		return ;
	}
	ll cres=1;
	set<ll> curr;
	rep(i,0,n)
	{
		curr.insert(a[i]);
		if(curr.size()>mid)
		{
			cres++;
			curr.clear();
			curr.insert(a[i]);
		}
	}
	res[mid]=cres;
	dnc(l,mid-1,cres,eval);
	dnc(mid+1,r,sval,cres);

}
int main()
{

	io

	cin>>n;
	rep(i,0,n)
	{
		cin>>a[i];
	}
	dnc(0,n-1,1,n);
	res[n]=1;
	rep(i,1,n+1)
	{
		cout<<res[i]<<" ";
	}

}


#include <bits/stdc++.h>

using namespace std;
#define IO                 \
	ios::sync_with_stdio(0); \
cin.tie(0);              \
cout.tie(0);
#define forn(i, n) for (int i = 0; i < n; i++)
#define forse(i, s,e) for (int i = s; i < e; i++)
#define pb push_back
#define pf push_front
#define rb pop_back
#define rf pop_front
#define mp make_pair
#define all(vec) vec.begin(), vec.end()
#define getcurrtime() \
	cerr << "Time = " << ((double)clock() / CLOCKS_PER_SEC) << endl

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<vector<ll>> Matrix;
const ll P = (1000 * 1000 * 1000) + 7;
const int arrn = 1e5+5;
const int arrn2 = 1e3;
const int sqr = 1000;
int n,cnt;
vector<int> jus(arrn,-1);
vector<int> cur(arrn,0);
vector<int> col(arrn,0);
vector<int> sq[150];
void pre(){
	forn(i,n){
		cur[i] = jus[col[i]];
		jus[col[i]] = i;
	}
	int i = 0;
	while(i*sqr < n){
		for(int j = i*sqr;j< min(n,(i+1)*sqr);j++){
			sq[i].pb(cur[j]);
		}
		sort(all(sq[i]));
		i++;
	}
}

int find(int l,int k){
	int nblock = l/sqr;
	nblock++;
	int cnt = 0;
	forse(i,l,min(n,sqr*nblock)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i] < l) return i;
	}
	while(nblock*sqr < n){
		int curnt = upper_bound(all(sq[nblock]),l-1) - sq[nblock].begin();
		if(cnt + curnt > k) break;
		cnt += curnt;
		nblock++;
	}
	forse(i,nblock*sqr,min(n,(nblock+1)*sqr)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i]<l) return i;
	}
	return min(n,(nblock+1)*sqr);
}
void solve() {
	int ans[arrn] = {};
	cin >> n;
	forn(i,n) cin >> col[i];
	cnt = n/sqr;
	pre();
	forn(k,n){
		int i = 0;
		while(i < n){
			i = find(i,k+1);
			ans[k]++;
		}
	}
	forn(i,n){
		cout << ans[i] << ' ';
	}
}
int main() {
	IO;
	int T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define IO                 \
	ios::sync_with_stdio(0); \
cin.tie(0);              \
cout.tie(0);
#define forn(i, n) for (int i = 0; i < n; i++)
#define forse(i, s,e) for (int i = s; i < e; i++)
#define pb push_back
#define pf push_front
#define rb pop_back
#define rf pop_front
#define mp make_pair
#define all(vec) vec.begin(), vec.end()
#define getcurrtime() \
	cerr << "Time = " << ((double)clock() / CLOCKS_PER_SEC) << endl

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<vector<ll>> Matrix;
const ll P = (1000 * 1000 * 1000) + 7;
const int arrn = 1e5+5;
const int arrn2 = 1e3;
const int sqr = 1000;
int n,cnt;
vector<int> jus(arrn,-1);
vector<int> cur(arrn,0);
vector<int> col(arrn,0);
vector<int> sq[150];
void pre(){
	forn(i,n){
		cur[i] = jus[col[i]];
		jus[col[i]] = i;
	}
	int i = 0;
	while(i*sqr < n){
		for(int j = i*sqr;j< min(n,(i+1)*sqr);j++){
			sq[i].pb(cur[j]);
		}
		i++;
		sort(all(sq[i]));
	}
}

int find(int l,int k){
	int nblock = l/sqr;
	nblock++;
	int cnt = 0;
	forse(i,l,min(n,sqr*nblock)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i] < l) return i;
	}
	while(nblock*sqr < n){
		int curnt = upper_bound(all(sq[nblock]),l-1) - sq[nblock].begin();
		if(cnt + curnt > k) break;
		cnt += curnt;
		nblock++;
	}
	forse(i,nblock*sqr,min(n,(nblock+1)*sqr)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i]<l) return i;
	}
	return min(n,(nblock+1)*sqr);
}
void solve() {
	int ans[arrn] = {};
	cin >> n;
	forn(i,n) cin >> col[i];
	cnt = n/sqr;
	pre();
	forn(k,n){
		int i = 0;
		while(i < n){
			i = find(i,k+1);
			ans[k]++;
		}
	}
	forn(i,n){
		cout << ans[i] << ' ';
	}
}
int main() {
	IO;
	int T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define IO                 \
	ios::sync_with_stdio(0); \
cin.tie(0);              \
cout.tie(0);
#define forn(i, n) for (int i = 0; i < n; i++)
#define forse(i, s,e) for (int i = s; i < e; i++)
#define pb push_back
#define pf push_front
#define rb pop_back
#define rf pop_front
#define mp make_pair
#define all(vec) vec.begin(), vec.end()
#define getcurrtime() \
	cerr << "Time = " << ((double)clock() / CLOCKS_PER_SEC) << endl

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<vector<ll>> Matrix;
const ll P = (1000 * 1000 * 1000) + 7;
int n;
const int arrn = 2048;
const int arrn2 = 1e3;
int cnt;

set<int> ks[201][201];

int col[100002] = {};
void pre(){
	forn(i,cnt){
		set<int> tem;
		forse(j,i*arrn,(i+1)*arrn){
			if((i+1)*arrn > n) break;
			else{
				tem.insert(col[j]);
			}
		}
		ks[i][i] = tem;
		for(int j = i-1;j >=0;j--){
			tem.insert(ks[i-1][j].begin(),ks[i-1][j].end());
			ks[i][j] = tem;
		}
	}
}
int ind(int k,int co){
	int z = k/arrn;
	z++;
	set<int> tem;
	forse(i,k,min(z*arrn,n)){
		tem.insert(col[i]);
		if((int)tem.size() > co)
			return i;
	}
	int al = z;
	while(al < cnt &&  (int)tem.size() + (int)ks[al][z].size() < co){
		al++;
	}
	al--;
	al = min(al,cnt);
	tem.insert(ks[al][z].begin(),ks[al][z].end());
	z = min((al+1)*arrn-1,n);
	while(z < n && (int)tem.size() <= co){
		z++;
		tem.insert(col[z]);
	}
	return z;
}
int val(int k){
	int out = 0;
	int in = 0;
	while(in != n){
		in = ind(in,k);
		out++;
	}
	return out;
}
void solve() {
	cin >> n;
  cnt = n/arrn;
	forn(i,n) cin >> col[i];
	pre();
	forn(i,n){
		cout << val(i+1) << ' ';
	}
}
int main() {
	IO;
	int T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define IO                 \
	ios::sync_with_stdio(0); \
cin.tie(0);              \
cout.tie(0);
#define forn(i, n) for (int i = 0; i < n; i++)
#define forse(i, s,e) for (int i = s; i < e; i++)
#define pb push_back
#define pf push_front
#define rb pop_back
#define rf pop_front
#define mp make_pair
#define all(vec) vec.begin(), vec.end()
#define getcurrtime() \
	cerr << "Time = " << ((double)clock() / CLOCKS_PER_SEC) << endl

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<vector<ll>> Matrix;
const ll P = (1000 * 1000 * 1000) + 7;
const int arrn = 1e5+5;
const int arrn2 = 1e3;
const int sqr = 1000;
int n,cnt;
vector<int> jus(arrn,-1);
vector<int> cur(arrn,0);
vector<int> col(arrn,0);
vector<int> sq[150];
void pre(){
	forn(i,n){
		cur[i] = jus[col[i]];
		jus[col[i]] = i;
	}
	int i = 0;
	while(i*sqr < n){
		for(int j = i*sqr;j< min(n,(i+1)*sqr);j++){
			sq[i].pb(cur[j]);
		}
		i++;
		sort(all(sq[i]));
	}
}

int find(int l,int k){
	int nblock = l/sqr;
	nblock++;
	int cnt = 0;
	forse(i,l,min(n,sqr*nblock)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i] < l) return i;
	}
	while(nblock*sqr < n){
		int curnt = upper_bound(all(sq[nblock]),l-1) - sq[nblock].begin();
		if(cnt + curnt > k) break;
		cnt += k;
		nblock++;
	}
	forse(i,nblock*sqr,min(n,(nblock+1)*sqr)){
		if(cnt < k && cur[i] < l) cnt++;
		else if(cnt == k && cur[i]<l) return i;
	}
	return n;
}
void solve() {
	int ans[arrn] = {};
	cin >> n;
	forn(i,n) cin >> col[i];
	cnt = n/sqr;
	pre();
	forn(k,n){
		int i = 0;
		while(i < n){
			i = find(i,k+1);
			ans[k]++;
		}
	}
	forn(i,n){
		cout << ans[i] << ' ';
	}
}
int main() {
	IO;
	int T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}


#include <iostream>
#include <algorithm>
using namespace std;
#pragma warning (disable: 4996)

int N, A[1 << 17], C[1 << 17], B[1 << 17];

int solve(int pos) {
	for (int i = 1; i <= N; i++) C[i] = 0;

	int L = 1, cnt = 0, types = 0;
	for (int i = 1; i <= N; i++) {
		if (C[A[i]] == 0) {
			if (types == pos) {
				types = 0; cnt++;
				for (int j = L; j < i; j++) C[A[j]] = 0;
				L = i;
			}
			C[A[i]] = 1;
			types++;
		}
	}
	cnt++;
	return cnt;
}

int main() {
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) scanf("%d", &A[i]);

	int TT = 1000;
	for (int i = 1; i <= TT; i++) B[i] = solve(i);
	int E = N;
	for (int i = 1; i <= N; i++) {
		int cl = 1, cr = N + 1, cm, maxn = 0;
		for (int j = 1; j <= 20; j++) {
			cm = (cl + cr) / 2;
			int G = solve(cm);
			if (G >= i) { maxn = max(maxn, cm); cl = cm; }
			else { cr = cm; }
		}
		for (int j = maxn + 1; j <= E; j++) B[j] = i - 1;
		E = maxn; if (E <= TT) break;
	}
	for (int i = 1; i <= N; i++) { if (i >= 2) printf(" "); printf("%d", B[i]); } printf("\n");
	return 0;
}


#include <iostream>
#include <algorithm>
using namespace std;
#pragma warning (disable: 4996)

int N, A[1 << 17], C[1 << 17], B[1 << 17];

int solve(int pos) {
	for (int i = 1; i <= N; i++) C[i] = 0;

	int L = 1, cnt = 0, types = 0;
	for (int i = 1; i <= N; i++) {
		if (C[A[i]] == 0) {
			if (types == pos) {
				types = 0; cnt++;
				for (int j = L; j < i; j++) C[A[j]] = 0;
			}
			C[A[i]] = 1;
			types++;
		}
	}
	cnt++;
	return cnt;
}

int main() {
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) scanf("%d", &A[i]);

	int TT = 1000;
	for (int i = 1; i <= TT; i++) B[i] = solve(i);
	int E = N;
	for (int i = 1; i <= N; i++) {
		int cl = 1, cr = N + 1, cm, maxn = 0;
		for (int j = 1; j <= 20; j++) {
			cm = (cl + cr) / 2;
			int G = solve(cm);
			if (G >= i) { maxn = max(maxn, cm); cl = cm; }
			else { cr = cm; }
		}
		for (int j = maxn + 1; j <= E; j++) B[j] = i - 1;
		E = maxn; if (E <= TT) break;
	}
	for (int i = 1; i <= N; i++) { if (i >= 2) printf(" "); printf("%d", B[i]); } printf("\n");
	return 0;
}


#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <numeric>
#pragma warning(disable:4996)

#define INF 10000000
#define MOD 1000000007
#define MAXN 100005
using namespace std;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	vector<int>a(n);
	vector<int>s(MAXN, -1), t(MAXN, -1);
	for (int i = 0; i < n; i++) {
		cin >> a[i];
		s[i] = t[a[i]];
		t[a[i]] = i;
	}
	t.assign(n + 1, 0);
	vector<int>k(MAXN, -1);
	for (int i = 0; i <= n; i++)k[i] = i;
	for (int i = 1; i <= n; i++) {
		int ret = 0;
		int j = 0;
		while (j < n) {
			int x = t[j], p = j;
			j = k[j];
			while (j < n && x <= i) {
				if (s[j] < p)x++;
				j++;
			}
			if (x > i)j--;
			ret++;
			t[p] = i;
			k[p] = j;
		}
		cout << ret << " ";
	}
	//cout << "\n";
	return 0;
}


#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <numeric>
#pragma warning(disable:4996)

#define INF 10000000
#define MOD 1000000007
#define MAXN 100005
using namespace std;
int n;
int a[MAXN],c[MAXN],r[MAXN];

int f(int k){
	memset(c, -1, sizeof(c));
	int ret = 0;
	int ct = 0;
	for (int j = 1; j <= n; j++){
		if (c[a[j]] == ret)
			continue;
		c[a[j]] = ret;
		ct++;
		if (ct>k){
			ct = 1;
			ret++;
			c[a[j]] = ret;
		}
	}
	return ret + 1;
}

void solve(int ll, int rr){
	if (ll>rr)return;
	r[ll] = f(ll);
	r[rr] = f(rr);

	if (r[ll] == r[rr]){
		for (int i = ll + 1; i<rr; i++)
			r[i] = r[ll];
		return;
	}
	solve(ll + 1, (ll + rr) / 2);
	solve((ll + rr) / 2 + 1, rr - 1);
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];

	solve(1, n);
	for (int i = 1; i <= n; i++) {
		cout << r[i] << " ";
	}
	cout << "\n";
	return 0;
}


#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
#include <numeric>
#pragma warning(disable:4996)

#define INF 10000000
#define MOD 1000000007
#define MAXN 100005
using namespace std;

int a[MAXN], s[MAXN], t[MAXN],k[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	//vector<int>a(n);
	//vector<int>s(MAXN, -1), t(MAXN, -1);
	for (int i = 0; i <= n; i++) {
		s[i] = t[i] = -1;
	}
	for (int i = 0; i < n; i++) {
		cin >> a[i];
		s[i] = t[a[i]];
		t[a[i]] = i;
	}
	for (int i = 0; i <= n; i++)t[i] = 0;
	for (int i = 0; i <= n; i++)k[i] = i;
	for (int i = 1; i <= n; i++) {
		int ret = 0;
		int j = 0;
		while (j < n) {
			int x = t[j], p = j;
			j = k[j];
			while (j < n && x <= i) {
				if (s[j] < p)x++;
				j++;
			}
			if (x > i)j--;
			ret++;
			t[p] = i;
			k[p] = j;
		}
		cout << ret << " ";
	}
	cout << "\n";
	return 0;
}


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

#define M 1000000007
#define MM 998244353
#define ll long long
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define memf(a) memset(a,false,sizeof(a))
#define all(v) v.begin(),v.end()
#define sz(a) (ll)a.size()
#define F first
#define S second
#define PI 3.1415926536
#define INF 2000000000000000000
#define endl "\n"
#define _time_ 1.0 * clock() / CLOCKS_PER_SEC
#define popcount(x) __builtin_popcountll(x)
//RNG based on mersenne_twister
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
ll power(ll b,ll e,ll m)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b%m,e/2,m)%m;
	return power(b*b%m,e/2,m);
}
ll power( ll b, ll e)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b,e/2);
	return power(b*b,e/2);
}
template<typename T, typename U> static inline void amin(T &x, U y){ if(y<x) x=y; }
template<typename T, typename U> static inline void amax(T &x, U y){ if(x<y) x=y; }
const int N=100005;
const int NN=N*45;
ll a[N],n;
struct node{
	ll val,L,R;
	node (): L(-1),R(-1),val(0){};
	node(ll x) : L(-1),R(-1),val(x){};
};
ll lst[N];
struct PERTREE{
	node tree[NN];
	int cursz=0;
	ll buildTree(ll st,ll en)
	{
		ll v = cursz++;
		tree[v]=node();
		if(st==en)
			return v;
		ll mid=(st+en)>>1;
		tree[v].L=buildTree(st,mid);
		tree[v].R=buildTree(mid+1,en);
		return v;
	}
	ll update(ll v,ll st,ll en,ll pos,ll val)
	{
		ll u=cursz++;
		tree[u]=node(tree[v].val+val);
		if(st==en)
			return u;
		ll mid=(st+en)>>1;
		if(pos<=mid)
			tree[u].L=update(tree[v].L,st,mid,pos,val);
		else
			tree[u].R=update(tree[v].R,mid+1,en,pos,val);
		tree[u].L=(tree[u].L==-1)?tree[v].L:tree[u].L;
		tree[u].R=(tree[u].R==-1)?tree[v].R:tree[u].R;
		return u;
	}
	ll query(ll v,ll st,ll en,ll k)
	{
		if(tree[v].val<=k)
			return en;
		if(st==en)
			return st;
		ll mid=(st+en)>>1;
		if(k<=tree[tree[v].L].val)
			return query(tree[v].L,st,mid,k);
		else
			return query(tree[v].R,mid+1,en,k-tree[tree[v].L].val);
	}
};
PERTREE seg;
ll roots[N];
int _runtimeTerror_()
{
	ll i;
	cin>>n;
	for(i=0;i<n;++i)
		cin>>a[i];
	for(i=1;i<=n+2;++i)
		lst[i]=-1;
	ll root= seg.buildTree(0,n-1);
	roots[n]=root;
	for(i=n-1;i>=0;--i)
	{
		root=roots[i+1];
		if(lst[a[i]]!=-1)
			root=seg.update(root,0,n-1,lst[a[i]],-1);
		lst[a[i]]=i;
		roots[i]=seg.update(root,0,n-1,i,1);
	}
	for(i=1;i<=n;++i)
	{
		ll ans=0;
		ll pos=-1;
		while(pos<n-1)
		{
			pos=seg.query(roots[pos+1],0,n-1,i);
			++ans;
		}
		cout<<ans<<" ";
	}
	return 0;
}

int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	#ifdef runSieve
		sieve();
	#endif
	#ifdef NCR
		initialize();
	#endif
	int TESTS=1;
	//cin>>TESTS;
	while(TESTS--)
		_runtimeTerror_();
	cerr<<"\n"<<_time_;
	return 0;
}


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

#define M 1000000007
#define MM 998244353
#define ll long long
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define memf(a) memset(a,false,sizeof(a))
#define all(v) v.begin(),v.end()
#define sz(a) (ll)a.size()
#define F first
#define S second
#define PI 3.1415926536
#define INF 2000000000000000000
#define endl "\n"
#define _time_ 1.0 * clock() / CLOCKS_PER_SEC
#define popcount(x) __builtin_popcountll(x)
//RNG based on mersenne_twister
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
ll power(ll b,ll e,ll m)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b%m,e/2,m)%m;
	return power(b*b%m,e/2,m);
}
ll power( ll b, ll e)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b,e/2);
	return power(b*b,e/2);
}
template<typename T, typename U> static inline void amin(T &x, U y){ if(y<x) x=y; }
template<typename T, typename U> static inline void amax(T &x, U y){ if(x<y) x=y; }
const int N=100005;
const int NN=N*45;
ll a[N],n;
struct node{
	ll val,L,R;
	node (): L(-1),R(-1),val(0){};
	node(ll x) : L(-1),R(-1),val(x){};
};
ll lst[N];
struct PERTREE{
	node tree[NN];
	int cursz=0;
	ll buildTree(ll st,ll en)
	{
		ll v = cursz++;
		tree[v]=node();
		if(st==en)
			return v;
		ll mid=(st+en)>>1;
		tree[v].L=buildTree(st,mid);
		tree[v].R=buildTree(mid+1,en);
		return v;
	}
	ll update(ll v,ll st,ll en,ll pos,ll val)
	{
		ll u=cursz++;
		tree[u]=node(tree[v].val+val);
		if(st==en)
			return u;
		ll mid=(st+en)>>1;
		if(pos<=mid)
			tree[u].L=update(tree[v].L,st,mid,pos,val);
		else
			tree[u].R=update(tree[v].R,mid+1,en,pos,val);
		tree[u].L=(tree[u].L==-1)?tree[v].L:tree[u].L;
		tree[u].R=(tree[u].R==-1)?tree[v].R:tree[u].R;
		return u;
	}
	ll query(ll v,ll st,ll en,ll k)
	{
		if(tree[v].val<=k)
			return en;
		if(tree[v].L==-1)
			return st;
		ll mid=(st+en)>>1;
		if(k<=tree[tree[v].L].val)
			return query(tree[v].L,st,mid,k);
		else
			return query(tree[v].R,mid+1,en,k-tree[tree[v].L].val);
	}
};
PERTREE seg;
ll roots[N];
int _runtimeTerror_()
{
	ll i;
	cin>>n;
	for(i=0;i<n;++i)
		cin>>a[i];
	for(i=1;i<=n+2;++i)
		lst[i]=-1;
	ll root= seg.buildTree(0,n-1);
	roots[n]=root;
	for(i=n-1;i>=0;--i)
	{
		root=roots[i+1];
		if(lst[a[i]]!=-1)
			root=seg.update(root,0,n-1,lst[a[i]],-1);
		lst[a[i]]=i;
		roots[i]=seg.update(root,0,n-1,i,1);
	}
	for(i=1;i<=n;++i)
	{
		ll ans=0;
		ll pos=-1;
		while(pos<n-1)
		{
			pos=seg.query(roots[pos+1],0,n-1,i);
			++ans;
		}
		cout<<ans<<" ";
	}
	return 0;
}

int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	#ifdef runSieve
		sieve();
	#endif
	#ifdef NCR
		initialize();
	#endif
	int TESTS=1;
	//cin>>TESTS;
	while(TESTS--)
		_runtimeTerror_();
	cerr<<"\n"<<_time_;
	return 0;
}


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

#define M 1000000007
#define MM 998244353
#define ll long long
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define memf(a) memset(a,false,sizeof(a))
#define all(v) v.begin(),v.end()
#define sz(a) (ll)a.size()
#define F first
#define S second
#define PI 3.1415926536
#define INF 2000000000000000000
#define endl "\n"
#define _time_ 1.0 * clock() / CLOCKS_PER_SEC
#define popcount(x) __builtin_popcountll(x)
//RNG based on mersenne_twister
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
ll power(ll b,ll e,ll m)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b%m,e/2,m)%m;
	return power(b*b%m,e/2,m);
}
ll power( ll b, ll e)
{
	if(e==0) return 1;
	if(e&1) return b*power(b*b,e/2);
	return power(b*b,e/2);
}
template<typename T, typename U> static inline void amin(T &x, U y){ if(y<x) x=y; }
template<typename T, typename U> static inline void amax(T &x, U y){ if(x<y) x=y; }
const int N=100005;
const int NN=N*45;
ll a[N],n;
struct node{
	ll val,L,R;
	node (): L(-1),R(-1),val(0){};
	node(ll x) : L(-1),R(-1),val(x){};
};
ll lst[N];
struct PERTREE{
	node tree[NN];
	int cursz=0;
	ll buildTree(ll st,ll en)
	{
		ll v = cursz++;
		tree[v]=node();
		if(st==en)
			return v;
		ll mid=(st+en)>>1;
		tree[v].L=buildTree(st,mid);
		tree[v].R=buildTree(mid+1,en);
		return v;
	}
	ll update(ll v,ll st,ll en,ll pos,ll val)
	{
		ll u=cursz++;
		tree[u]=node(tree[v].val+val);
		if(st==en)
			return u;
		ll mid=(st+en)>>1;
		if(pos<=mid)
			tree[u].L=update(tree[v].L,st,mid,pos,val);
		else
			tree[u].R=update(tree[v].R,mid+1,en,pos,val);
		tree[u].L=(tree[u].L==-1)?tree[v].L:tree[u].L;
		tree[u].R=(tree[u].R==-1)?tree[v].R:tree[u].R;
		return u;
	}
	ll query(ll v,ll st,ll en,ll k)
	{
		if(tree[v].val<=k)
			return en+1;
		if(st==en)
			return st;
		ll mid=(st+en)>>1;
		if(k<tree[tree[v].L].val)
			return query(tree[v].L,st,mid,k);
		else
			return query(tree[v].R,mid+1,en,k-tree[tree[v].L].val);
	}
};
PERTREE seg;
ll roots[N];
int _runtimeTerror_()
{
	ll i;
	cin>>n;
	for(i=0;i<n;++i)
		cin>>a[i];
	for(i=1;i<=n+2;++i)
		lst[i]=-1;
	ll root= seg.buildTree(0,n-1);
	roots[n]=root;
	for(i=n-1;i>=0;--i)
	{
		root=roots[i+1];
		if(lst[a[i]]!=-1)
			root=seg.update(root,0,n-1,lst[a[i]],-1);
		lst[a[i]]=i;
		roots[i]=seg.update(root,0,n-1,i,1);
	}
	int x=1;
	//cout<<seg.query(roots[1],0,n-1,1)<<endl;
	for(i=1;i<=n;++i)
	{
		ll ans=0;
		ll pos=0;
		while(pos<n)
		{
			pos=seg.query(roots[pos],0,n-1,i);
			++ans;
		}
		cout<<ans<<" ";
	}
	return 0;
}

int main()
{
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	#ifdef runSieve
		sieve();
	#endif
	#ifdef NCR
		initialize();
	#endif
	int TESTS=1;
	//cin>>TESTS;
	while(TESTS--)
		_runtimeTerror_();
	cerr<<"\n"<<_time_;
	return 0;
}


// In the name of Allah.
// We're nothing and you're everything.
// Ya Ali!

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

typedef long long ll;
const int maxn = 1e5 + 14;
struct node{
    int s = 0;
    node *L, *R;
}  *root[maxn];
typedef node * ni;
int n, a[maxn], last_seen[maxn];
int get_next(int &k, ni id, int l = 0, int r = n){
    if(id -> s <= k){
        k -= id -> s;
        return n;
    }
    if(l + 1 == r)
        return l;
    int mid = (l + r) / 2;
    int ans = get_next(k, id -> L, l, mid);
    return ans == n ? get_next(k, id -> R, mid, r) : ans;
}
ni build(int l = 0, int r = n){
    ni id = new node;
    if(l + 1 == r)
        return id;
    int mid = (l + r) / 2;
    id -> L = build(l, mid);
    id -> R = build(mid, r);
    return id;
}
ni upd(int p, int x, ni guide, int l = 0, int r = n){
    assert(guide);
    ni id = new node(*guide);
    if(l + 1 == r){
        id -> s += x;
        return id;
    }
    int mid = (l + r) / 2;
    if(p < mid)
        id -> L = upd(p, x, guide -> L, l, mid);
    else
        id -> R = upd(p, x, guide -> R, mid, r);
    id -> s = id -> L -> s + id -> R -> s;
    return id;
}
int main(){
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];
    root[n] = build();
    for(int i = n - 1; i >= 0; i--){
        if(last_seen[ a[i] ]){
            root[i] = upd(last_seen[ a[i] ], -1, root[i + 1]);
            root[i] = upd(i, +1, root[i]);
        }
        else
            root[i] = upd(i, +1, root[i + 1]);
        last_seen[ a[i] ] = i;
    }
    // cerr << get_next(root[])
    for(int k = 1; k <= n; k++){
        int ans = 0, i = 0;
        for(; i < n; ans++)
            i = get_next(*new int(k), root[i]);
        cout << ans << ' ';
    }
    cout << '\n';
}


// In the name of Allah.
// We're nothing and you're everything.
// Ya Ali!

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

typedef long long ll;
const int maxn = 1e5 + 14;
struct node{
    int s;
    node *L, *R;
};
typedef node * ni;
int get_next(int s, int e, int k, int l = 0, int r = 0, ni id){
    if(e <= l || r <= s)
        return -1;

}
int main(){
    ios::sync_with_stdio(0), cin.tie(0);

}


#include <bits/stdc++.h>

using namespace std;
const int MAXN = 1e5 + 5;

class HJT {
public:
    int ch[MAXN * 70][2], sum[MAXN * 70];
    int tot;

    inline void push_up(int rt) {
        sum[rt] = sum[ch[rt][0]] + sum[ch[rt][1]];
    }

    int change(int rt, int pos, int val, int be, int en) {
        int nrt = ++tot;
        ch[nrt][0] = ch[nrt][1] = sum[nrt] = 0;
        if (be == en) {
            sum[nrt] = sum[rt] + val;
            return nrt;
        }
        int mid = (be + en) >> 1;
        if (pos <= mid) {
            ch[nrt][0] = change(ch[rt][0], pos, val, be, mid);
            ch[nrt][1] = ch[rt][1];
        } else {
            ch[nrt][0] = ch[rt][0];
            ch[nrt][1] = change(ch[rt][1], pos, val, mid + 1, en);
        }
        push_up(nrt);
        return nrt;
    }

    int query(int rt, int L, int R, int be, int en) {
        if (L <= be && en <= R) return sum[rt];
        int mid = (be + en) >> 1;
        int ans = 0;
        if (L <= mid) ans += query(ch[rt][0], L, R, be, mid);
        if (R > mid) ans += query(ch[rt][1], L, R, mid + 1, en);
        return ans;
    }

} tree;

int ai[MAXN], root[MAXN], pre[MAXN];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &ai[i]);
    }
    root[0] = 0;
    for (int i = 1; i <= n; i++) {
        int x = ai[i];
        if (pre[x]) {
            int tmp = tree.change(root[i - 1], pre[x], -1, 1, n);
            root[i] = tree.change(tmp, i, 1, 1, n);
        } else {
            root[i] = tree.change(root[i - 1], i, 1, 1, n);
        }
        pre[x] = i;
    }
    for (int k = 1; k <= n; k++) {  // enum k
        int pos = 1, res = 0;
        while (pos <= n) {
            int L = pos, R = n;
            while (L < R) {
                int mid = (L + R + 1) >> 1;
                int tmp = tree.query(root[mid], pos, mid, 1, n);
                if (tmp > k) R = mid - 1;
                else L = mid;
            }
            pos = L + 1;
            res++;
        }
        printf("%d ", res);
    }

}


#include <bits/stdc++.h>

using namespace std;
const int MAXN = 1e5 + 5;

class HJT {
public:
    int ch[MAXN * 70][2], sum[MAXN * 70];
    int tot;

    inline void push_up(int rt) {
        sum[rt] = sum[ch[rt][0]] + sum[ch[rt][1]];
    }

    int change(int rt, int pos, int val, int be, int en) {
        int nrt = ++tot;
        ch[nrt][0] = ch[nrt][1] = sum[nrt] = 0;
        if (be == en) {
            sum[nrt] = sum[rt] + val;
            return nrt;
        }
        int mid = (be + en) >> 1;
        if (pos <= mid) {
            ch[nrt][0] = change(ch[rt][0], pos, val, be, mid);
            ch[nrt][1] = ch[rt][1];
        } else {
            ch[nrt][0] = ch[rt][0];
            ch[nrt][1] = change(ch[rt][1], pos, val, mid + 1, en);
        }
        push_up(nrt);
        return nrt;
    }

    int query(int rt, int k, int be, int en) {
        if (be == en) return be;
        int mid = (be + en) >> 1;
        if (sum[ch[rt][0]] >= k) return query(ch[rt][0], k, be, mid);
        else return query(ch[rt][1], k - sum[ch[rt][0]], mid+1, en);
    }

} tree;

int ai[MAXN], root[MAXN], pre[MAXN];

int main() {
    int n;
    set<int> st;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &ai[i]);
//        if (st.count(ai[i])) {
//            printf("%d\n", ai[i]);
//        } else st.insert(ai[i]);
    }
//    for (int i = 1; i <= n; i++) {
//        printf("%d ", ai[i]);
//        if (i % 9 == 0) printf("\n");
//    }
//    printf("\n");

    root[n+1] = 0;
    for (int i = n; i >= 1; i--) {
        int x = ai[i];
        if (pre[x]) {
            int tmp = tree.change(root[i + 1], pre[x], -1, 1, n);
            root[i] = tree.change(tmp, i, 1, 1, n);
        } else {
            root[i] = tree.change(root[i + 1], i, 1, 1, n);
        }
        pre[x] = i;
    }
    for (int k = 1; k <= n; k++) {  // enum k
//        if (k == 9) {
//            printf("qwq");
//        }
        int pos = 1, res = 0;
        while (pos <= n) {
            // if (k == 9) printf("%d\n", ai[pos]);
            if (tree.sum[root[pos]] <= k) {
                res++;
                break;
            } else {
                pos = tree.query(root[pos], k+1, 1, n);
                res++;
            }
        }
        printf("%d ", res);
    }

}

/*
100
39 78 71 61 54 13 17 81 30 33 83 98 44 10 45 87 75 47 70 84 41 86 49 94 85 91 37 64 5 56 67 79 28 89 50 53 77 93 81 14 97 67 58 6 48 60 89 62 29 3 38 8 88 19 66 63 100 17 43 97 21 12 58 76 2 78 25 73 99 11 27 18 57 46 4 72 68 45 74 18 2 80 51 52 42 59 55 35 1 95 42 92 36 40 59 15 7 21 97 53

 */


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n, a[MAXN], ans[MAXN];
bool mark[MAXN];

int ret(int i){
	int ot = 0, cnt = 0, cur = 0;
	while( cur < n){
		cnt = 0;
		ot ++;
		int mx = cur;
		vector< int > vec;
		while( mx < n){
			if( mark[a[mx]] ){
				mx ++;
				continue;
			}
			if( cnt + 1 > i) break;
			cnt ++;
			mark[a[mx]] = true, vec.push_back(a[mx]), mx ++;
		}
		cur = mx;
		for(int i = 0; i < vec.size(); i ++)
			mark[vec[i]] = false;
	}
	return ot;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i ++) cin >> a[i], ans[i] = INT_MAX;
	ans[n] = INT_MAX;
	for(int i = 1; i <= sqrt(n) + 100;i ++)
		ans[i] = ret(i);
	for(int i = max(0, (int)sqrt(n) - 90); i >= 1; i --){
		int l = 1, r = n, anp = n;
		while( l <= r){
			int mid = (l + r)/2;
			if( ret(mid) <= i) anp = mid, r = mid - 1;
			else l = mid + 1;
		}
		for(int j = anp; j <= n; j ++) ans[j] = min(i, ans[j]);
	}

	for(int i = 2; i <= n; i ++) ans[i] = min(ans[i], ans[i - 1]);
	for(int i = 1; i <= n;i ++)
		cout << ans[i] << " ";

	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n, a[MAXN], ans[MAXN];
bool mark[MAXN];

int ret(int i){
	int ot = 0, cnt = 0, cur = 0;
	while( cur < n){
		cnt = 0;
		ot ++;
		int mx = cur;
		vector< int > vec;
		while( mx < n){
			if( mark[a[mx]] ){
				mx ++;
				continue;
			}
			if( cnt + 1 > i) break;
			cnt ++;
			mark[a[mx]] = true, vec.push_back(a[mx]), mx ++;
		}
		cur = mx;
		for(int i = 0; i < vec.size(); i ++)
			mark[vec[i]] = false;
	}
	return ot;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i ++) cin >> a[i], ans[i] = INT_MAX;
	ans[n] = INT_MAX;
	for(int i = 1; i <= sqrt(n) + 4;i ++)
		ans[i] = ret(i);
	for(int i = sqrt(n); i >= 1; i --){
		int l = 1, r = n, anp = n;
		while( l < r){
			int mid = (l + r)/2;
			if( ret(mid) <= i) anp = mid, r = mid - 1;
			else l = mid + 1;
		}
		for(int j = anp; j <= n; j ++) ans[j] = min(i, ans[j]);
	}

	for(int i = 2; i <= n; i ++) ans[i] = min(ans[i], ans[i - 1]);
	for(int i = 1; i <= n;i ++)
		cout << ans[i] << " ";

	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n, a[MAXN], ans[MAXN];
bool mark[MAXN];

int ret(int i){
	int ot = 0, cnt = 0, cur = 0;
	while( cur < n){
		cnt = 0;
		ot ++;
		int mx = cur;
		vector< int > vec;
		while( mx < n){
			if( mark[a[mx]] ){
				mx ++;
				continue;
			}
			if( cnt + 1 > i) break;
			cnt ++;
			mark[a[mx]] = true, vec.push_back(a[mx]), mx ++;
		}
		cur = mx;
		for(int i = 0; i < vec.size(); i ++)
			mark[vec[i]] = false;
	}
	return ot;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i ++) cin >> a[i], ans[i] = INT_MAX;
	ans[n] = INT_MAX;
	for(int i = 1; i <= sqrt(n) + 5;i ++)
		ans[i] = ret(i);
	for(int i = sqrt(n); i >= 1; i --){
		int l = 1, r = n, anp = n;
		while( l <= r){
			int mid = (l + r)/2;
			if( ret(mid) <= i) anp = mid, r = mid - 1;
			else l = mid + 1;
		}
		for(int j = anp; j <= n; j ++) ans[j] = min(i, ans[j]);
	}

	for(int i = 2; i <= n; i ++) ans[i] = min(ans[i], ans[i - 1]);
	for(int i = 1; i <= n;i ++)
		cout << ans[i] << " ";

	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n, a[MAXN], af[MAXN], mind[MAXN];
vector< int > qu[MAXN];
bool mark[MAXN];
int seg[MAXN * 4], ans[MAXN];

void add(int ind, int val, int b = 0, int e = n, int id = 1){
	if( b + 1 == e){
		seg[id] += val;
		return;
	}
	int mid = (b + e)/2;
	if( ind < mid) add(ind, val, b, mid, id*2);
	else add(ind, val, mid, e, id*2 + 1);
	seg[id] = seg[id*2] + seg[id*2 + 1];
}

int bs(int val, int b = 0, int e = n,int id = 1){
	if( b + 1 == e) return b;
	int mid = (b + e)/2;
	if( val <= seg[id*2])
		return bs(val, b, mid, id*2);
	else return bs(val - seg[id*2], mid, e, id*2 + 1);
}
int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0; i < n;i ++){
		cin >> a[i], a[i] --;
		mind[i] = af[i] = -1;
		qu[0].push_back(i + 1);
	}

	mind[a[n - 1]] = n - 1;
	for(int i = n - 2; i >= 0; i --)
		af[i] = mind[a[i]], mind[a[i]] = i;

	for(int i = 0; i < n;i ++){
		if( !mark[a[i]])
			add(i, 1);
		mark[a[i]] = true;
	}
	for(int i = 0;i < n;i ++){
		for(int j = 0; j < qu[i].size();j ++){
			int k = qu[i][j];
			ans[k] ++;
			if( seg[1] > k){
				int it = bs(k + 1);
				qu[it].push_back(k);
			}
		}
		add(i, -1);
		if( af[i] >= 0) add(af[i], 1);
	}

	for(int i = 1; i <= n; i++)
		cout << ans[i] << " ";
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
int n, a[MAXN], ans[MAXN];
bool mark[MAXN];

int ret(int i){
	int ot = 0, cnt = 0, cur = 0;
	while( cur < n){
		cnt = 0;
		ot ++;
		int mx = cur;
		vector< int > vec;
		while( mx < n){
			if( mark[a[mx]] ){
				mx ++;
				continue;
			}
			if( cnt + 1 > i) break;
			cnt ++;
			mark[a[mx]] = true, vec.push_back(a[mx]), mx ++;
		}
		cur = mx;
		for(int i = 0; i < vec.size(); i ++)
			mark[vec[i]] = false;
	}
	return ot;
}

int main(){
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i ++) cin >> a[i], ans[i] = INT_MAX;
	ans[n] = INT_MAX;
	for(int i = 1; i <= 500;i ++)
		ans[i] = ret(i);
	for(int i = 200; i >= 1; i --){
		int l = 1, r = n, anp = n;
		while( l <= r){
			int mid = (l + r)/2;
			if( ret(mid) <= i) anp = mid, r = mid - 1;
			else l = mid + 1;
		}
		for(int j = anp; j <= n; j ++) ans[j] = min(i, ans[j]);
	}

	for(int i = 2; i <= n; i ++) ans[i] = min(ans[i], ans[i - 1]);
	for(int i = 1; i <= n;i ++)
		cout << ans[i] << " ";

	return 0;
}


#include <bits/stdc++.h>

typedef long long ll;
typedef long double ld;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define PRECISION std::cout << std::fixed << std::setprecision(20);

using namespace std;

const ll inf = 1e18;
const int N = 2e6+1;
const ll mod = 1e9+7;

int tree[4*N], lid[4*N], rid[4*N], roots[N], sz;

int build(int ss, int se){
    int id = sz++;

    if(ss!=se){
        int mid = (ss+se)/2;
        lid[id] = build(ss, mid);
        rid[id] = build(mid+1, se);
    }

    return id;
}

int update(int qi, int ss, int se, int id, int val){
    int nid = sz++;

    if(ss==se){
        tree[nid] = val;
    }else{
        int mid = (ss+se)/2;
        if(qi <= mid){
            lid[nid] = update(qi, ss, mid, lid[id], val);
            rid[nid] = rid[id];
        }else{
            lid[nid] = lid[id];
            rid[nid] = update(qi, mid+1, se, rid[id], val);
        }
        tree[nid] = tree[lid[nid]] + tree[rid[nid]];
    }

    return nid;
}

int query(int ss, int se, int id, int k){
    if(ss==se) return ss;

    int mid = (ss+se)/2;

    if(tree[lid[id]] >= k){
        return query(ss, mid, lid[id], k);
    }else{
        return query(mid+1, se, rid[id], k - tree[lid[id]]);
    }
}

int arr[N], lst[N];

void solve(){
    int n;
    cin>>n;

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

    roots[n+1] = build(1, n);

    for(int i=n;i>=1;i--){
        if(lst[arr[i]]){
            roots[i] = update(lst[arr[i]], 1, n, roots[i+1], 0);
            lst[arr[i]] = i;
            roots[i] = update(lst[arr[i]], 1, n, roots[i], 1);
        }else{
            lst[arr[i]] = i;
            roots[i] = update(lst[arr[i]], 1, n, roots[i+1], 1);
        }
    }

    for(int i=1;i<=n;i++){
        int pos = 1;
        int cnt = 0;
        while(pos<=n){
            if(tree[roots[pos]] <= i){
                pos = n+1;
            }else{
                pos = query(1, n, roots[pos], i+1);
            }
            cnt++;
        }

        cout<<cnt<<" \n"[i==n];
    }

}

int main(){
    FASTIO;
    PRECISION;

    int t = 1;

    while(t--){
        solve();
    }
}


#include <bits/stdc++.h>

typedef long long ll;
typedef long double ld;
#define FASTIO ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define PRECISION std::cout << std::fixed << std::setprecision(20);

using namespace std;

const ll inf = 1e18;
const int N = 2e5+1;
const ll mod = 1e9+7;

int tree[4*N], lid[4*N], rid[4*N], roots[N], sz;

int build(int ss, int se){
    int id = sz++;

    if(ss!=se){
        int mid = (ss+se)/2;
        lid[id] = build(ss, mid);
        rid[id] = build(mid+1, se);
    }

    return id;
}

int update(int qi, int ss, int se, int id, int val){
    int nid = sz++;

    if(ss==se){
        tree[nid] = val;
    }else{
        int mid = (ss+se)/2;
        if(qi <= mid){
            lid[nid] = update(qi, ss, mid, lid[id], val);
            rid[nid] = rid[id];
        }else{
            lid[nid] = lid[id];
            rid[nid] = update(qi, mid+1, se, rid[id], val);
        }
        tree[nid] = tree[lid[nid]] + tree[rid[nid]];
    }

    return nid;
}

int query(int ss, int se, int id, int k){
    if(ss==se) return ss;

    int mid = (ss+se)/2;

    if(tree[lid[id]] >= k){
        return query(ss, mid, lid[id], k);
    }else{
        return query(mid+1, se, rid[id], k - tree[lid[id]]);
    }
}

int arr[N], lst[N];

void solve(){
    int n;
    cin>>n;

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

    roots[n+1] = build(1, n);

    for(int i=n;i>=1;i--){
        if(lst[arr[i]]){
            roots[i] = update(lst[arr[i]], 1, n, roots[i+1], 0);
            lst[arr[i]] = i;
            roots[i] = update(lst[arr[i]], 1, n, roots[i], 1);
        }else{
            lst[arr[i]] = i;
            roots[i] = update(lst[arr[i]], 1, n, roots[i+1], 1);
        }
    }

    for(int i=1;i<=n;i++){
        int pos = 1;
        int cnt = 0;
        while(pos<=n){
            if(tree[roots[pos]] <= i){
                pos = n+1;
            }else{
                pos = query(1, n, roots[pos], i+1);
            }
            cnt++;
        }

        cout<<cnt<<" \n"[i==n];
    }

}

int main(){
    FASTIO;
    PRECISION;

    int t = 1;

    while(t--){
        solve();
    }
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define all(a) (a).begin(), (a).end()
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC taraget("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define sz() size()
#define fr first
#define sc second
#define pi pair<int,int>
#define int long long
#define pii pair<pair<int,int>,int>
#define mp make_pair
#define rc(s) return cout<<s,0
#define rcc(s) cout<<s,exit(0)
using namespace std;

const int mod=1e9+7;
const int modp=1999999973;
const int modulo=998244353;

const int nmax=100005;

int n,a[nmax],_next=-1,app[nmax],root_nod[nmax],lmao;

struct nod{
    int val,le,ri;
};

vector<nod>aint;

void build(int l,int r){
    ++_next;
    aint.emplace_back();
    aint.back().val=0;
    if(l!=r){
        int mid=l+(r-l)/2;
        int curr=_next;
        aint[curr].le=(_next+1);
        build(l,mid);
        aint[curr].ri=(_next+1);
        build(mid+1,r);
        return;
    }
}

void update(int l,int r,int pos,int val,int last){
    _next++;
    aint.emplace_back();
    if(l==r){
        aint[_next].val=(aint[last].val+val);
        return;
    }
    else{
        int mid=l+(r-l)/2;
        int curr=_next;
        aint[curr].le=aint[last].le;
        aint[curr].ri=aint[last].ri;
        if(pos<=mid){
            aint[curr].le=(_next+1);
            update(l,mid,pos,val,aint[last].le);
        }
        else{
            aint[curr].ri=(_next+1);
            update(mid+1,r,pos,val,aint[last].ri);
        }
        aint[curr].val=aint[aint[curr].le].val+aint[aint[curr].ri].val;
        return;
    }
}

void modify(int l,int r,int pos,int curr,int last){
    if(l==r){
        if(curr!=0 || aint[last].val==0) lmao=l;
        return;
    }
    else{
        int mid=l+(r-l)/2;
        if(aint[aint[last].le].val>curr){
            modify(l,mid,pos,curr,aint[last].le);
        }
        else{
            curr-=aint[aint[last].le].val;
            if(curr==0) lmao=mid;
            modify(mid+1,r,pos,curr,aint[last].ri);
        }
    }
}

int32_t main(){
   // ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
    srand(chrono::steady_clock::now().time_since_epoch().count());
    ifstream cin("input.in");
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    build(1,n);
    for(int i=n;i>=1;i--){
        if(app[a[i]]){
            int curr=(_next+1);
            update(1,n,app[a[i]],-1,root_nod[i+1]);
            root_nod[i]=(_next+1);
            update(1,n,i,1,curr);
            app[a[i]]=i;
        }
        else{
            app[a[i]]=i;
            root_nod[i]=(_next+1);
            update(1,n,i,1,root_nod[i+1]);
        }
    }
    for(int i=1;i<=n;i++){
        int ans=0;
        int j=1;
        while(j!=n+1){
            lmao=0;
            modify(1,n,j,i,root_nod[j]);
            j=lmao;
            j++;
            ans++;
        }
        cout << ans << ' ';
    }
    cout << '\n';
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define all(a) (a).begin(), (a).end()
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC taraget("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define sz() size()
#define fr first
#define sc second
#define pi pair<int,int>
#define int long long
#define pii pair<pair<int,int>,int>
#define mp make_pair
#define rc(s) return cout<<s,0
#define rcc(s) cout<<s,exit(0)
using namespace std;

const int mod=1e9+7;
const int modp=1999999973;
const int modulo=998244353;

const int nmax=100005;

int n,a[nmax],_next=-1,app[nmax],root_nod[nmax],lmao;

struct nod{
    int val,le,ri;
};

vector<nod>aint;

void build(int l,int r){
    ++_next;
    aint.emplace_back();
    aint.back().val=0;
    if(l!=r){
        int mid=l+(r-l)/2;
        int curr=_next;
        aint[curr].le=(_next+1);
        build(l,mid);
        aint[curr].ri=(_next+1);
        build(mid+1,r);
        return;
    }
}

void update(int l,int r,int pos,int val,int last){
    _next++;
    aint.emplace_back();
    if(l==r){
        aint[_next].val=(aint[last].val+val);
        return;
    }
    else{
        int mid=l+(r-l)/2;
        int curr=_next;
        aint[curr].le=aint[last].le;
        aint[curr].ri=aint[last].ri;
        if(pos<=mid){
            aint[curr].le=(_next+1);
            update(l,mid,pos,val,aint[last].le);
        }
        else{
            aint[curr].ri=(_next+1);
            update(mid+1,r,pos,val,aint[last].ri);
        }
        aint[curr].val=aint[aint[curr].le].val+aint[aint[curr].ri].val;
        return;
    }
}

void modify(int l,int r,int pos,int curr,int last){
    if(l==r){
        if(curr!=0 || aint[last].val==0) lmao=l;
        return;
    }
    else{
        int mid=l+(r-l)/2;
        if(aint[aint[last].le].val>curr){
            modify(l,mid,pos,curr,aint[last].le);
        }
        else{
            curr-=aint[aint[last].le].val;
            if(curr==0) lmao=mid;
            modify(mid+1,r,pos,curr,aint[last].ri);
        }
    }
}

int32_t main(){
    ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
    srand(chrono::steady_clock::now().time_since_epoch().count());
   // ifstream cin("input.in");
    cin >> n;
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    build(1,n);
    for(int i=n;i>=1;i--){
        if(app[a[i]]){
            int curr=(_next+1);
            update(1,n,app[a[i]],-1,root_nod[i+1]);
            root_nod[i]=(_next+1);
            update(1,n,i,1,curr);
            app[a[i]]=i;
        }
        else{
            app[a[i]]=i;
            root_nod[i]=(_next+1);
            update(1,n,i,1,root_nod[i+1]);
        }
    }
    for(int i=1;i<=n;i++){
        int ans=0;
        int j=1;
        while(j!=n+1){
            lmao=0;
            modify(1,n,j,i,root_nod[j]);
            j=lmao;
            j++;
            ans++;
        }
        cout << ans << ' ';
    }
    cout << '\n';
}


#include <bits/stdc++.h>

using namespace std;

typedef pair< int,int > PII;
typedef long long int lo;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(lo i=1;i<=n;i++)
#define mid (bas+son)/2

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 300005;
const lo mod = 1000000007;

lo n,m,cev,b,a[li],vis[li],sol,cevap[li],sondu[li];
string s;
vector<lo> v;

void naivesol(lo solve){
	memset(vis,0,sizeof(vis));
	memset(sondu,-1,sizeof(sondu));
	lo dif=0;
	sol=0;
	FOR{
		if(vis[a[i]]==0 || (sondu[a[i]]<=i-solve && sondu[a[i]]!=-1)){dif++;vis[a[i]]=1;}
		if(dif>solve){dif=0;sol++;i--;}
		sondu[a[i]]=i;
	}
	return ;
}

void DAC(lo L,lo R,lo OPTL,lo OPTR){
	//~ cout<<L<<" "<<R<<" "<<OPTL<<" "<<OPTR<<endl;
	if(L>R) return ;
	if(OPTL==OPTR) cevap[(L+R)/2]=OPTR;
	else{naivesol((L+R)/2);cevap[(L+R)/2]=sol+1;}
	DAC(L,(L+R)/2-1,cevap[(L+R)/2],OPTR);
	DAC((L+R)/2+1,R,OPTL,cevap[(L+R)/2]);
}

int main(){
	scanf("%lld",&n);
	FOR{
		scanf("%lld",&a[i]);
	}
	//~ cout<<"**\n";
	DAC(1,n,1,n);
	//~ cout<<"**\n";
	FOR{
		printf("%lld ",cevap[i]);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef pair< int,int > PII;
typedef long long int lo;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(lo i=1;i<=n;i++)
#define mid (bas+son)/2

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 300005;
const lo mod = 1000000007;

lo n,m,cev,b,a[li],vis[li],sol,cevap[li],sondu[li];
string s;
vector<lo> v;

void naivesol(lo solve){
	memset(vis,0,sizeof(vis));
	FOR{
		sondu[a[i]]=-inf;
	}
	lo dif=0;
	sol=0;
	FOR{
		//~ if(solve==3) cout<<sondu[a[i]]<<endl;
		if(vis[a[i]]==0 || (sondu[a[i]]<i-dif)){dif++;}
		if(dif>solve){dif=0;sol++;i--;continue;}
		sondu[a[i]]=i;vis[a[i]]=1;
	}
	return ;
}

void DAC(lo L,lo R,lo OPTL,lo OPTR){
	//~ cout<<L<<" "<<R<<" "<<OPTL<<" "<<OPTR<<endl;
	if(L>R) return ;
	if(OPTL==OPTR) cevap[(L+R)/2]=OPTR;
	else{naivesol((L+R)/2);cevap[(L+R)/2]=sol+1;}
	DAC(L,(L+R)/2-1,cevap[(L+R)/2],OPTR);
	DAC((L+R)/2+1,R,OPTL,cevap[(L+R)/2]);
}

int main(){
	scanf("%lld",&n);
	FOR{
		scanf("%lld",&a[i]);
	}
	//~ cout<<"**\n";
	DAC(1,n,1,n);
	//~ cout<<"**\n";
	FOR{
		printf("%lld ",cevap[i]);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef pair< int,int > PII;
typedef long long int lo;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(lo i=1;i<=n;i++)
#define mid (bas+son)/2

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 100005;
const lo mod = 1000000007;

lo n,m,cev,b,a[li],vis[li],sol,cevap[li];
string s;
vector<lo> v;

void naivesol(lo solve){
	memset(vis,0,sizeof(vis));
	lo dif=0;
	sol=0;
	FOR{
		if(vis[a[i]]==0){dif++;vis[a[i]]=1;}
		if(dif>solve){dif=0;sol++;i--;memset(vis,0,sizeof(vis));}

	}
	return ;
}

void DAC(lo L,lo R,lo OPTL,lo OPTR){
	//~ cout<<L<<" "<<R<<" "<<OPTL<<" "<<OPTR<<endl;
	if(L>R) return ;
	if(OPTL==OPTR) cevap[(L+R)/2]=OPTR;
	else{naivesol((L+R)/2);cevap[(L+R)/2]=sol+1;}
	DAC(L,(L+R)/2-1,cevap[(L+R)/2],OPTR);
	DAC((L+R)/2+1,R,OPTL,cevap[(L+R)/2]);
}

int main(){
	scanf("%lld",&n);
	FOR{
		scanf("%lld",&a[i]);
	}
	//~ cout<<"**\n";
	DAC(1,n,1,n);
	//~ cout<<"**\n";
	FOR{
		printf("%lld ",cevap[i]);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef pair< int,int > PII;
typedef long long int lo;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(lo i=1;i<=n;i++)
#define mid (bas+son)/2

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 300005;
const lo mod = 1000000007;

lo n,m,cev,b,a[li],vis[li],sol,cevap[li],sondu[li];
string s;
vector<lo> v;

void naivesol(lo solve){
	memset(vis,0,sizeof(vis));
	FOR{
		sondu[a[i]]=-inf;
	}
	lo dif=0;
	sol=0;
	FOR{
		if(vis[a[i]]==0 || (sondu[a[i]]<=i-solve && sondu[a[i]]!=-1)){dif++;vis[a[i]]=1;}
		if(dif>solve){dif=0;sol++;i--;}
		sondu[a[i]]=i;
	}
	return ;
}

void DAC(lo L,lo R,lo OPTL,lo OPTR){
	//~ cout<<L<<" "<<R<<" "<<OPTL<<" "<<OPTR<<endl;
	if(L>R) return ;
	if(OPTL==OPTR) cevap[(L+R)/2]=OPTR;
	else{naivesol((L+R)/2);cevap[(L+R)/2]=sol+1;}
	DAC(L,(L+R)/2-1,cevap[(L+R)/2],OPTR);
	DAC((L+R)/2+1,R,OPTL,cevap[(L+R)/2]);
}

int main(){
	scanf("%lld",&n);
	FOR{
		scanf("%lld",&a[i]);
	}
	//~ cout<<"**\n";
	DAC(1,n,1,n);
	//~ cout<<"**\n";
	FOR{
		printf("%lld ",cevap[i]);
	}
	return 0;
}


//Sani buyuk Osman Pasa Plevneden cikmam diyor.
//FatihSultanMehmedHan
//Abdulhamid Han
//Bismillahirrahmanirrahim
//█▀█─█──█──█▀█─█─█
//█▄█─█──█──█▄█─█▄█
//█─█─█▄─█▄─█─█─█─█

#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")

#include <bits/stdc++.h>

using namespace std;

typedef long long lo;
typedef pair< int,int > PII;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(int i=1;i<=n;i++)
#define mid ((start+end)/2)
#define ort ((bas+son)/2)

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 500005;
const lo mod = 1000000007;

int n,m,b[li],a[li],k,flag,t,dizi[li],vis[li],dp[li];
int cev;
string s;
vector<int> v;

inline int naivesol(int k){
	memset(vis,0,sizeof(vis));
	int grup=1,farkli=0;
	FOR{
		//~ cout<<i<<endl;;
		if(vis[a[i]]==grup)continue;
		if(farkli+1>k){grup++;i--;farkli=0;continue;}
		farkli++;
		vis[a[i]]=grup;
	}
	return grup;
}

inline void dac(int start,int end,int optl,int optr){
	//~ cout<<start<<end<<endl;
	if(start>end)return ;
	if(optl==optr){dp[mid]=optl;}

	else{
		int at=naivesol(mid);
		dp[mid]=at;
	}
	dac(start,mid-1,dp[mid],optr),dac(mid+1,end,optl,dp[mid]);
}

int main(void){
	scanf("%d",&n);
	FOR{
		scanf("%d",&a[i]);
	}
	dac(1,n,1,n);
	FOR{
		printf("%d ",dp[i]);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef pair< int,int > PII;
typedef long long int lo;

#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fio() ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
#define FOR for(lo i=1;i<=n;i++)
#define mid (bas+son)/2

const lo MAX = -1000000000000000000;
const lo MIN = 1000000000000000000;
const lo inf = 1000000000;
const lo KOK = 100000;
const lo LOG = 30;
const lo li = 300005;
const lo mod = 1000000007;

lo n,m,cev,b,a[li],vis[li],sol,cevap[li],sondu[li],grup;
string s;
vector<lo> v;

void naivesol(lo solve){
	memset(vis,0,sizeof(vis));
	FOR{
		sondu[a[i]]=-inf;
	}
	lo dif=0;
	grup=0;
	sol=0;
	FOR{
		//~ if(solve==3) cout<<sondu[a[i]]<<endl;
		if(vis[a[i]]==0 || (sondu[a[i]]<grup+1)){dif++;}
		if(dif>solve){dif=0;sol++;i--;grup=i;continue;}
		sondu[a[i]]=i;vis[a[i]]=1;
	}
	return ;
}

void DAC(lo L,lo R,lo OPTL,lo OPTR){
	//~ cout<<L<<" "<<R<<" "<<OPTL<<" "<<OPTR<<endl;
	if(L>R) return ;
	if(OPTL==OPTR) cevap[(L+R)/2]=OPTR;
	else{naivesol((L+R)/2);cevap[(L+R)/2]=sol+1;}
	DAC(L,(L+R)/2-1,cevap[(L+R)/2],OPTR);
	DAC((L+R)/2+1,R,OPTL,cevap[(L+R)/2]);
}

int main(){
	scanf("%lld",&n);
	FOR{
		scanf("%lld",&a[i]);
	}
	//~ cout<<"**\n";
	DAC(1,n,1,n);
	//~ cout<<"**\n";
	FOR{
		printf("%lld ",cevap[i]);
	}
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

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

	int sq=1;
	for(;sq*sq<=n;sq++) sq++;

	vector<int> res(n);
	for(int i=1;i<=sq;i++){
		int co=0;
		vector<int> ta(n);
		int pre=0;
		for(int j=0;j<n;j++){
			if(ta[a[j]]==0) co++;
			if(co>i){
				while(pre<j){
					ta[a[pre]]=0;
					pre++;
				}
				co=1;
				res[i-1]++;
			}
			ta[a[j]]++;
		}
		res[i-1]++;
	}
	int te=0;
	vector<int> mark(n);
	while(true){
		te++;
		vector<int> ta(n);
		int co=0,le=0,ri=0;
		for(int i=sq;i<n;i++){
			if(mark[i]==n) break;
			while(ri<mark[i]){
				if(ta[a[ri]]==0) co++;
				ta[a[ri]]++;
				ri++;
			}
			while(le<mark[i]){
				ta[a[le]]--;
				if(ta[a[le]]==0) co--;
				le++;
			}

			while(ri<n && co<=(i+1)){
				if(ta[a[ri]]==0) co++;
				ta[a[ri]]++;
				ri++;
			}
			if(co>(i+1)){
				ri--;
				ta[a[ri]]--;
				if(ta[a[ri]]==0) co--;
			}
			mark[i]=ri;
			if(ri==n) res[i]=te;
		}
		if(mark[sq]==n) break;
	}
	for(int i=0;i<n;i++) cout << res[i] << " ";
	cout << "\n";
	return 0;
}


#include<bits/stdc++.h>

using namespace std;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

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

	int sq=1;
	while(sq*sq<n) sq++;

	vector<int> res(n), mark(n);
	for(int i=1;i<=sq;i++){
		int co=0;
		vector<int> ta(n);
		int pre=0;
		for(int j=0;j<n;j++){
			if(ta[a[j]]==0) co++;
			if(co>i){
				while(pre<j){
					ta[a[pre]]=0;
					pre++;
				}
				co=1;
				res[i-1]++;
			}
			ta[a[j]]++;
		}
		res[i-1]++;
	}
	int te=0;
	while(n>2 && true){
		te++;
		vector<int> ta(n);
		int co=0,le=0,ri=0;
		for(int i=sq;i<n;i++){
			if(mark[i]==n) break;
			while(ri<mark[i]){
				if(ta[a[ri]]==0) co++;
				ta[a[ri]]++;
				ri++;
			}
			while(le<mark[i]){
				ta[a[le]]--;
				if(ta[a[le]]==0) co--;
				le++;
			}

			while(ri<n && co<=(i+1)){
				if(ta[a[ri]]==0) co++;
				ta[a[ri]]++;
				ri++;
			}
			if(co>(i+1)){
				ri--;
				ta[a[ri]]--;
				if(ta[a[ri]]==0) co--;
			}
			mark[i]=ri;
			if(ri==n) res[i]=te;
		}
		if(mark[sq]==n) break;
	}
	for(int i=0;i<n;i++) cout << res[i] << " ";
	cout << "\n";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=100005,INF=1<<30;

int dpx[MAX],dpy[MAX];

// https://kopricky.github.io/code/DataStructure_Advanced/wavelet_matrix.htmlから引用
struct BitRank {
    // block: bit 列を管理, count: block ごとに立っている 1 の数を管理
    vector<unsigned long long> block;
    vector<unsigned int> count;
    BitRank(){}
    void resize(const unsigned int num){
        block.resize(((num + 1) >> 6) + 1, 0);
        count.resize(block.size(), 0);
    }
    // i ビット目を val(0,1) にセット
    void set(const unsigned int i, const unsigned long long val){
        block[i >> 6] |= (val << (i & 63));
    }
    void build(){
        for(unsigned int i = 1; i < block.size(); i++){
            count[i] = count[i - 1] + __builtin_popcountll(block[i - 1]);
        }
    }
    // [0, i) ビットの 1 の数
    unsigned int rank1(const unsigned int i) const {
        return count[i >> 6] +
        __builtin_popcountll(block[i >> 6] & ((1ULL << (i & 63)) - 1ULL));
    }
    // [i, j) ビットの 1 の数
    unsigned int rank1(const unsigned int i, const unsigned int j) const {
        return rank1(j) - rank1(i);
    }
    // [0, i) ビットの 0 の数
    unsigned int rank0(const unsigned int i) const {
        return i - rank1(i);
    }
    // [i, j) ビットの 0 の数
    unsigned int rank0(const unsigned int i, const unsigned int j) const {
        return rank0(j) - rank0(i);
    }
};

class WaveletMatrix
{
private:
    unsigned int height;
    vector<BitRank> B;
    vector<int> pos;
public:
    WaveletMatrix(){}
    WaveletMatrix(vector<int> vec) :
    WaveletMatrix(vec, *max_element(vec.begin(), vec.end()) + 1){}
    // sigma:文字の種類数
    WaveletMatrix(vector<int> vec, const unsigned int sigma){
        init(vec, sigma);
    }
    void init(vector<int>& vec, const unsigned int sigma){
        height = (sigma == 1) ? 1 : (64 - __builtin_clzll(sigma - 1));
        B.resize(height), pos.resize(height);
        for(unsigned int i = 0; i < height; ++i){
            B[i].resize(vec.size());
            for(unsigned int j = 0; j < vec.size(); ++j) {
                B[i].set(j, get(vec[j], height - i - 1));
            }
            B[i].build();
            auto it = stable_partition(vec.begin(), vec.end(), [&](int c){
                return !get(c, height - i - 1);
            });
            pos[i] = it - vec.begin();
        }
    }
    // val の i ビット目の値を返す(0,1)
    int get(const int val, const int i){
        return val >> i & 1;
    }
    // [l, r) の間に現れる値 val の数
    int rank(const int val, const int l, const int r){
        return rank(val, r) - rank(val, l);
    }
    // [0, i) の間に現れる値 val の数
    int rank(int val, int i){
        int p = 0;
        for(unsigned int j = 0; j < height; ++j){
            if(get(val, height - j - 1)){
                p = pos[j] + B[j].rank1(p);
                i = pos[j] + B[j].rank1(i);
            }else{
                p = B[j].rank0(p);
                i = B[j].rank0(i);
            }
        }
        return i - p;
    }
    // [l, r) の k(0,1,2...) 番目に小さい値を返す
    int quantile(int k, int l, int r){
        int res = 0;
        for(unsigned int i = 0; i < height; ++i){
            const int j = B[i].rank0(l, r);
            if(j > k){
                l = B[i].rank0(l);
                r = B[i].rank0(r);
            }else{
                l = pos[i] + B[i].rank1(l);
                r = pos[i] + B[i].rank1(r);
                k -= j;
                res |= (1 << (height - i - 1));
            }
        }
        return res;
    }
    int rangefreq(const int i, const int j, const int a, const int b,
                  const int l, const int r, const int x){
        if(i == j || r <= a || b <= l) return 0;
        const int mid = (l + r) >> 1;
        if(a <= l && r <= b){
            return j - i;
        }else{
            const int left = rangefreq(B[x].rank0(i), B[x].rank0(j), a, b, l, mid, x + 1);
            const int right = rangefreq(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                        a, b, mid, r, x + 1);
            return left + right;
        }
    }
    // [l,r) で値が [a,b) 内に含まれる数を返す
    int rangefreq(const int l, const int r, const int a, const int b){
        return rangefreq(l, r, a, b, 0, 1 << height, 0);
    }
    int rangemin(const int i, const int j, const int a, const int b,
                 const int l, const int r, const int x, const int val){
        if(i == j || r <= a || b <= l) return -1;
        if(r - l == 1) return val;
        const int mid = (l + r) >> 1;
        const int res = rangemin(B[x].rank0(i),B[x].rank0(j),a,b,l,mid,x+1,val);
        if(res < 0) return rangemin(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                    a, b, mid, r, x + 1, val + (1 << (height - x - 1)));
        else return res;
    }
    // [l,r) で値が [a,b) 内に最小の数を返す(数が存在しない場合は -1 を返す)
    int rangemin(int l, int r, int a, int b){
        return rangemin(l, r, a, b, 0, 1 << height, 0, 0);
    }
};

template<typename T> class OrthogonalRangeCount
{
private:
    using ptt = pair<T, T>;
    const int sz;
    vector<T> X, Y;
    WaveletMatrix wm;

public:
    OrthogonalRangeCount(vector<ptt> candidate)
    : sz((int)candidate.size()), X(sz), Y(sz){
        sort(candidate.begin(), candidate.end());
        vector<int> vec(sz);
        for(int i = 0; i < sz; ++i){
            X[i] = candidate[i].first, Y[i] = candidate[i].second;
        }
        sort(Y.begin(), Y.end());
        Y.erase(unique(Y.begin(), Y.end()), Y.end());
        for(int i = 0; i < sz; ++i){
            vec[i] = lower_bound(Y.begin(), Y.end(), candidate[i].second) - Y.begin();
        }
        wm.init(vec, Y.size());

        for(int i=0;i<MAX;i++){
            dpx[i]=lower_bound(X.begin(), X.end(), i) - X.begin();
            dpy[i]=lower_bound(Y.begin(), Y.end(), i) - Y.begin();
        }
    }
    // [lx,rx) × [ly, ry) の長方形領域に含まれる点の数を答える
    int query(const T lx, const T ly, const T rx, const T ry){
        const int lxid = dpx[lx];//lower_bound(X.begin(), X.end(), lx) - X.begin();
        const int rxid = dpx[rx];//lower_bound(X.begin(), X.end(), rx) - X.begin();
        const int lyid = 0;
        const int ryid = dpy[ry];//lower_bound(Y.begin(), Y.end(), ry) - Y.begin();

        //cout<<lyid<<endl;
        if(lxid >= rxid || lyid >= ryid) return 0;
        return wm.rangefreq(lxid, rxid, lyid, ryid);
    }
};

vector<int> when[MAX];

int mem[20][MAX];

int main(){

    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;cin>>N;
    vector<int> A(N);
    for(int i=0;i<N;i++){
        cin>>A[i];
        when[A[i]].push_back(i);
    }

    vector<pair<int,int>> vec;
    for(int i=0;i<MAX;i++){
        for(int j=0;j+1<si(when[i]);j++){
            vec.push_back(mp(when[i][j],when[i][j+1]));
        }
    }
    OrthogonalRangeCount<int> orc(vec);

    int iii=0;
    for(int k=1;k<=N;k*=2){
        for(int i=0;i<N;i++){
            int now=i;
            int left=now,right=N;
            if(k>=2) left=mem[iii-1][i]+1;
            while(right-left>1){
                int mid=(left+right)/2;

                int cnt=mid-now+1-orc.query(now,INT_MIN,mid,mid+1);
                if(cnt<=k) left=mid+max(0,(k-cnt-1));
                else right=mid-max(0,(cnt-k-1));
            }
            if(left>=N) left=N-1;
            mem[iii][i]=left;
        }
        iii++;
    }

    for(int j=0;j<N;j++) mem[iii][j]=N-1;

    for(int k=1;k<=N;k++){
        int j=0;
        for(int i=20;;i--){
            if(k&(1<<i)){
                j=i;
                break;
            }
        }
        int ans=0,now=0;
        while(now<N){
            int left=mem[j][now],right=mem[j+1][now]+1;
            //cout<<left<<" "<<right<<endl;
            while(right-left>1){
                int mid=(left+right)/2;

                int cnt=mid-now+1-orc.query(now,INT_MIN,mid,mid+1);
                if(cnt<=k) left=mid+max(0,(k-cnt-1));
                else right=mid-max(0,(cnt-k-1));
            }

            ans++;
            now=left+1;
        }
        cout<<ans<<" ";
    }
    cout<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=100005;
const ll INF=1LL<<60;
// https://kopricky.github.io/code/DataStructure_Advanced/wavelet_matrix.htmlから引用
struct BitRank {
    // block: bit 列を管理, count: block ごとに立っている 1 の数を管理
    vector<unsigned long long> block;
    vector<unsigned int> count;
    BitRank(){}
    void resize(const unsigned int num){
        block.resize(((num + 1) >> 6) + 1, 0);
        count.resize(block.size(), 0);
    }
    // i ビット目を val(0,1) にセット
    void set(const unsigned int i, const unsigned long long val){
        block[i >> 6] |= (val << (i & 63));
    }
    void build(){
        for(unsigned int i = 1; i < block.size(); i++){
            count[i] = count[i - 1] + __builtin_popcountll(block[i - 1]);
        }
    }
    // [0, i) ビットの 1 の数
    unsigned int rank1(const unsigned int i) const {
        return count[i >> 6] +
        __builtin_popcountll(block[i >> 6] & ((1ULL << (i & 63)) - 1ULL));
    }
    // [i, j) ビットの 1 の数
    unsigned int rank1(const unsigned int i, const unsigned int j) const {
        return rank1(j) - rank1(i);
    }
    // [0, i) ビットの 0 の数
    unsigned int rank0(const unsigned int i) const {
        return i - rank1(i);
    }
    // [i, j) ビットの 0 の数
    unsigned int rank0(const unsigned int i, const unsigned int j) const {
        return rank0(j) - rank0(i);
    }
};

class WaveletMatrix
{
private:
    unsigned int height;
    vector<BitRank> B;
    vector<int> pos;
public:
    WaveletMatrix(){}
    WaveletMatrix(vector<int> vec) :
    WaveletMatrix(vec, *max_element(vec.begin(), vec.end()) + 1){}
    // sigma:文字の種類数
    WaveletMatrix(vector<int> vec, const unsigned int sigma){
        init(vec, sigma);
    }
    void init(vector<int>& vec, const unsigned int sigma){
        height = (sigma == 1) ? 1 : (64 - __builtin_clzll(sigma - 1));
        B.resize(height), pos.resize(height);
        for(unsigned int i = 0; i < height; ++i){
            B[i].resize(vec.size());
            for(unsigned int j = 0; j < vec.size(); ++j) {
                B[i].set(j, get(vec[j], height - i - 1));
            }
            B[i].build();
            auto it = stable_partition(vec.begin(), vec.end(), [&](int c){
                return !get(c, height - i - 1);
            });
            pos[i] = it - vec.begin();
        }
    }
    // val の i ビット目の値を返す(0,1)
    int get(const int val, const int i){
        return val >> i & 1;
    }
    // [l, r) の間に現れる値 val の数
    int rank(const int val, const int l, const int r){
        return rank(val, r) - rank(val, l);
    }
    // [0, i) の間に現れる値 val の数
    int rank(int val, int i){
        int p = 0;
        for(unsigned int j = 0; j < height; ++j){
            if(get(val, height - j - 1)){
                p = pos[j] + B[j].rank1(p);
                i = pos[j] + B[j].rank1(i);
            }else{
                p = B[j].rank0(p);
                i = B[j].rank0(i);
            }
        }
        return i - p;
    }
    // [l, r) の k(0,1,2...) 番目に小さい値を返す
    int quantile(int k, int l, int r){
        int res = 0;
        for(unsigned int i = 0; i < height; ++i){
            const int j = B[i].rank0(l, r);
            if(j > k){
                l = B[i].rank0(l);
                r = B[i].rank0(r);
            }else{
                l = pos[i] + B[i].rank1(l);
                r = pos[i] + B[i].rank1(r);
                k -= j;
                res |= (1 << (height - i - 1));
            }
        }
        return res;
    }
    int rangefreq(const int i, const int j, const int a, const int b,
                  const int l, const int r, const int x){
        if(i == j || r <= a || b <= l) return 0;
        const int mid = (l + r) >> 1;
        if(a <= l && r <= b){
            return j - i;
        }else{
            const int left = rangefreq(B[x].rank0(i), B[x].rank0(j), a, b, l, mid, x + 1);
            const int right = rangefreq(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                        a, b, mid, r, x + 1);
            return left + right;
        }
    }
    // [l,r) で値が [a,b) 内に含まれる数を返す
    int rangefreq(const int l, const int r, const int a, const int b){
        return rangefreq(l, r, a, b, 0, 1 << height, 0);
    }
    int rangemin(const int i, const int j, const int a, const int b,
                 const int l, const int r, const int x, const int val){
        if(i == j || r <= a || b <= l) return -1;
        if(r - l == 1) return val;
        const int mid = (l + r) >> 1;
        const int res = rangemin(B[x].rank0(i),B[x].rank0(j),a,b,l,mid,x+1,val);
        if(res < 0) return rangemin(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                    a, b, mid, r, x + 1, val + (1 << (height - x - 1)));
        else return res;
    }
    // [l,r) で値が [a,b) 内に最小の数を返す(数が存在しない場合は -1 を返す)
    int rangemin(int l, int r, int a, int b){
        return rangemin(l, r, a, b, 0, 1 << height, 0, 0);
    }
};

template<typename T> class OrthogonalRangeCount
{
private:
    using ptt = pair<T, T>;
    const int sz;
    vector<T> X, Y;
    WaveletMatrix wm;

public:
    OrthogonalRangeCount(vector<ptt> candidate)
    : sz((int)candidate.size()), X(sz), Y(sz){
        sort(candidate.begin(), candidate.end());
        vector<int> vec(sz);
        for(int i = 0; i < sz; ++i){
            X[i] = candidate[i].first, Y[i] = candidate[i].second;
        }
        sort(Y.begin(), Y.end());
        Y.erase(unique(Y.begin(), Y.end()), Y.end());
        for(int i = 0; i < sz; ++i){
            vec[i] = lower_bound(Y.begin(), Y.end(), candidate[i].second) - Y.begin();
        }
        wm.init(vec, Y.size());
    }
    // [lx,rx) × [ly, ry) の長方形領域に含まれる点の数を答える
    int query(const T lx, const T ly, const T rx, const T ry){
        const int lxid = lower_bound(X.begin(), X.end(), lx) - X.begin();
        const int rxid = lower_bound(X.begin(), X.end(), rx) - X.begin();
        const int lyid = lower_bound(Y.begin(), Y.end(), ly) - Y.begin();
        const int ryid = lower_bound(Y.begin(), Y.end(), ry) - Y.begin();
        if(lxid >= rxid || lyid >= ryid) return 0;
        return wm.rangefreq(lxid, rxid, lyid, ryid);
    }
};

vector<int> when[MAX];

int main(){

    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;cin>>N;
    vector<int> A(N);
    for(int i=0;i<N;i++){
        cin>>A[i];
        when[A[i]].push_back(i);
    }

    vector<pair<int,int>> vec;
    for(int i=0;i<MAX;i++){
        for(int j=0;j+1<si(when[i]);j++){
            vec.push_back(mp(when[i][j],when[i][j+1]));
        }
    }
    OrthogonalRangeCount<int> orc(vec);

    for(int k=1;k<=N;k++){
        int ans=0,now=0;
        while(now<N){
            int left=now,right=N;
            while(right-left>1){
                int mid=(left+right)/2;

                int cnt=mid-now+1-orc.query(now,INT_MIN,mid,mid+1);
                if(cnt<=k) left=mid;
                else right=mid;
            }

            ans++;
            now=left+1;
        }
        cout<<ans<<" ";
    }
    cout<<endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=100005,INF=1<<30;

int dpx[MAX],dpy[MAX];

// https://kopricky.github.io/code/DataStructure_Advanced/wavelet_matrix.htmlから引用
struct BitRank {
    // block: bit 列を管理, count: block ごとに立っている 1 の数を管理
    vector<unsigned long long> block;
    vector<unsigned int> count;
    BitRank(){}
    void resize(const unsigned int num){
        block.resize(((num + 1) >> 6) + 1, 0);
        count.resize(block.size(), 0);
    }
    // i ビット目を val(0,1) にセット
    void set(const unsigned int i, const unsigned long long val){
        block[i >> 6] |= (val << (i & 63));
    }
    void build(){
        for(unsigned int i = 1; i < block.size(); i++){
            count[i] = count[i - 1] + __builtin_popcountll(block[i - 1]);
        }
    }
    // [0, i) ビットの 1 の数
    unsigned int rank1(const unsigned int i) const {
        return count[i >> 6] +
        __builtin_popcountll(block[i >> 6] & ((1ULL << (i & 63)) - 1ULL));
    }
    // [i, j) ビットの 1 の数
    unsigned int rank1(const unsigned int i, const unsigned int j) const {
        return rank1(j) - rank1(i);
    }
    // [0, i) ビットの 0 の数
    unsigned int rank0(const unsigned int i) const {
        return i - rank1(i);
    }
    // [i, j) ビットの 0 の数
    unsigned int rank0(const unsigned int i, const unsigned int j) const {
        return rank0(j) - rank0(i);
    }
};

class WaveletMatrix
{
private:
    unsigned int height;
    vector<BitRank> B;
    vector<int> pos;
public:
    WaveletMatrix(){}
    WaveletMatrix(vector<int> vec) :
    WaveletMatrix(vec, *max_element(vec.begin(), vec.end()) + 1){}
    // sigma:文字の種類数
    WaveletMatrix(vector<int> vec, const unsigned int sigma){
        init(vec, sigma);
    }
    void init(vector<int>& vec, const unsigned int sigma){
        height = (sigma == 1) ? 1 : (64 - __builtin_clzll(sigma - 1));
        B.resize(height), pos.resize(height);
        for(unsigned int i = 0; i < height; ++i){
            B[i].resize(vec.size());
            for(unsigned int j = 0; j < vec.size(); ++j) {
                B[i].set(j, get(vec[j], height - i - 1));
            }
            B[i].build();
            auto it = stable_partition(vec.begin(), vec.end(), [&](int c){
                return !get(c, height - i - 1);
            });
            pos[i] = it - vec.begin();
        }
    }
    // val の i ビット目の値を返す(0,1)
    int get(const int val, const int i){
        return val >> i & 1;
    }
    // [l, r) の間に現れる値 val の数
    int rank(const int val, const int l, const int r){
        return rank(val, r) - rank(val, l);
    }
    // [0, i) の間に現れる値 val の数
    int rank(int val, int i){
        int p = 0;
        for(unsigned int j = 0; j < height; ++j){
            if(get(val, height - j - 1)){
                p = pos[j] + B[j].rank1(p);
                i = pos[j] + B[j].rank1(i);
            }else{
                p = B[j].rank0(p);
                i = B[j].rank0(i);
            }
        }
        return i - p;
    }
    // [l, r) の k(0,1,2...) 番目に小さい値を返す
    int quantile(int k, int l, int r){
        int res = 0;
        for(unsigned int i = 0; i < height; ++i){
            const int j = B[i].rank0(l, r);
            if(j > k){
                l = B[i].rank0(l);
                r = B[i].rank0(r);
            }else{
                l = pos[i] + B[i].rank1(l);
                r = pos[i] + B[i].rank1(r);
                k -= j;
                res |= (1 << (height - i - 1));
            }
        }
        return res;
    }
    int rangefreq(const int i, const int j, const int a, const int b,
                  const int l, const int r, const int x){
        if(i == j || r <= a || b <= l) return 0;
        const int mid = (l + r) >> 1;
        if(a <= l && r <= b){
            return j - i;
        }else{
            const int left = rangefreq(B[x].rank0(i), B[x].rank0(j), a, b, l, mid, x + 1);
            const int right = rangefreq(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                        a, b, mid, r, x + 1);
            return left + right;
        }
    }
    // [l,r) で値が [a,b) 内に含まれる数を返す
    int rangefreq(const int l, const int r, const int a, const int b){
        return rangefreq(l, r, a, b, 0, 1 << height, 0);
    }
    int rangemin(const int i, const int j, const int a, const int b,
                 const int l, const int r, const int x, const int val){
        if(i == j || r <= a || b <= l) return -1;
        if(r - l == 1) return val;
        const int mid = (l + r) >> 1;
        const int res = rangemin(B[x].rank0(i),B[x].rank0(j),a,b,l,mid,x+1,val);
        if(res < 0) return rangemin(pos[x] + B[x].rank1(i), pos[x] + B[x].rank1(j),
                                    a, b, mid, r, x + 1, val + (1 << (height - x - 1)));
        else return res;
    }
    // [l,r) で値が [a,b) 内に最小の数を返す(数が存在しない場合は -1 を返す)
    int rangemin(int l, int r, int a, int b){
        return rangemin(l, r, a, b, 0, 1 << height, 0, 0);
    }
};

template<typename T> class OrthogonalRangeCount
{
private:
    using ptt = pair<T, T>;
    const int sz;
    vector<T> X, Y;
    WaveletMatrix wm;

public:
    OrthogonalRangeCount(vector<ptt> candidate)
    : sz((int)candidate.size()), X(sz), Y(sz){
        sort(candidate.begin(), candidate.end());
        vector<int> vec(sz);
        for(int i = 0; i < sz; ++i){
            X[i] = candidate[i].first, Y[i] = candidate[i].second;
        }
        sort(Y.begin(), Y.end());
        Y.erase(unique(Y.begin(), Y.end()), Y.end());
        for(int i = 0; i < sz; ++i){
            vec[i] = lower_bound(Y.begin(), Y.end(), candidate[i].second) - Y.begin();
        }
        wm.init(vec, Y.size());

        for(int i=0;i<MAX;i++){
            dpx[i]=lower_bound(X.begin(), X.end(), i) - X.begin();
            dpy[i]=lower_bound(Y.begin(), Y.end(), i) - Y.begin();
        }
    }
    // [lx,rx) × [ly, ry) の長方形領域に含まれる点の数を答える
    int query(const T lx, const T ly, const T rx, const T ry){
        const int lxid = dpx[lx];//lower_bound(X.begin(), X.end(), lx) - X.begin();
        const int rxid = dpx[rx];//lower_bound(X.begin(), X.end(), rx) - X.begin();
        const int lyid = 0;
        const int ryid = dpy[ry];//lower_bound(Y.begin(), Y.end(), ry) - Y.begin();

        //cout<<lyid<<endl;
        if(lxid >= rxid || lyid >= ryid) return 0;
        return wm.rangefreq(lxid, rxid, lyid, ryid);
    }
};

vector<int> when[MAX];

int mem[20][MAX];

int main(){

    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;cin>>N;
    vector<int> A(N);
    for(int i=0;i<N;i++){
        cin>>A[i];
        when[A[i]].push_back(i);
    }

    vector<pair<int,int>> vec;
    for(int i=0;i<MAX;i++){
        for(int j=0;j+1<si(when[i]);j++){
            vec.push_back(mp(when[i][j],when[i][j+1]));
        }
    }
    OrthogonalRangeCount<int> orc(vec);

    int iii=0;
    for(int k=1;k<=N;k*=2){
        for(int i=0;i<N;i++){
            int now=i;
            int left=now,right=N;
            if(k>=2) left=mem[iii-1][i]+k-k/2;
            if(i) chmax(left,mem[iii][i-1]);
            while(right-left>1){
                int mid=(left+right)/2;

                int cnt=mid-now+1-orc.query(now,INT_MIN,mid,mid+1);
                if(cnt<=k) left=mid+max(0,(k-cnt-1));
                else right=mid-max(0,(cnt-k-1));
            }
            if(left>=N) left=N-1;
            mem[iii][i]=left;
        }
        iii++;
    }

    for(int j=0;j<N;j++) mem[iii][j]=N-1;

    for(int k=1;k<=N;k++){
        int j=0;
        for(int i=20;;i--){
            if(k&(1<<i)){
                j=i;
                break;
            }
        }
        int ans=0,now=0;
        while(now<N){
            int left=mem[j][now],right=mem[j+1][now]+1;
            //cout<<left<<" "<<right<<endl;
            while(right-left>1){
                int mid=(left+right)/2;

                int cnt=mid-now+1-orc.query(now,INT_MIN,mid,mid+1);
                if(cnt<=k) left=mid+max(0,(k-cnt-1));
                else right=mid-max(0,(cnt-k-1));
            }

            ans++;
            now=left+1;
        }
        cout<<ans<<" ";
    }
    cout<<endl;
}