#include<bits/stdc++.h>
using namespace std;
int n,m;
int cnt[3005];
pair<long long,int> w[3005],c[3005][3005];
bool vis[3005];
int sucnt=0;
int main()
{
	cin>>n>>m;//voters parties
	for(int i=1;i<=n;i++)
	{
		int x;
		long long y;
		cin>>x>>y;

		cnt[x]++;
		if(x==1)continue;
		sucnt++;
		w[sucnt].first=y;
		w[sucnt].second=i;
		c[x][cnt[x]]=make_pair(w[sucnt].first,i);
	}

	sort(w+1,w+sucnt+1);
	//cout<<w[1].first<<endl;
	for(int i=2;i<=m;i++)sort(c[i]+1,c[i]+cnt[i]+1);

	bool f=0;
	for(int i=1;i<=m;i++)
	{
		if(cnt[1]<=cnt[i])f=1;
	}
	if(!f)
	{
		cout<<0<<endl;
		return 0;
	}
	//cout<<cnt[1]<<endl;
	long long ans=1e14+7;
	for(int i=cnt[1];i<=n;i++)
	{
		//cout<<"#"<<i<<endl;
		long long res=0;
		int num=i-cnt[1];
		memset(vis,0,sizeof(vis));
		for(int j=2;j<=m;j++)//>i
		{
			//cout<<j<<" "<<cnt[j]-i+1<<endl;
			if(cnt[j]<=i-1)continue;
			for(int k=1;k<=cnt[j]-i+1;k++)
			{
				res+=c[j][k].first;
				//cout<<res<<endl;
				vis[c[j][k].second]=1;
				num--;
			}
		}
		if(num<0)continue;
		int k=1;
		while(num>0)
		{
			if(!vis[w[k].second])
			{
				res+=w[k].first;
				num--;
			}
			k++;
		}
		ans=min(ans,res);
	}
	cout<<ans<<endl;
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;
typedef std::pair<LL,int> Pii;
#define mp std::make_pair
#define N_max 100005
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

void prt(){
}

int findm(){//人最多，最小最小的集合
	int m=2,sz=otr[2].size();LL cc=(*otr[2].begin()).c;
	//if(sz==0)return m;
		for(int i=3;i<=n;++i){
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	//freopen("in.txt", "r", stdin);
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m=findm();
	LL cc;
	while(1){//to make num enough

		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
			m=findm();
			prt();
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc;
	while(1){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);
		//get the cheapst
		prt();
		m=findm();
		while((ber.size()+amt)<=otr[m].size()){
			ntemp=*all.begin();
			stemp.c=ntemp.c;
			stemp.p=ntemp.p;
			otr[ntemp.p].erase(ntemp);
			all.erase(ntemp);
			ber.insert(stemp);
			tprc+=stemp.c;
			prt();
			m=findm();
		}
		if(tprc>=prc)break;
		prc=tprc;
		prt();
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

int findm(){//人最多，最小最小的集合
	int m=-1,sz=0;LL cc;
		for(int i=2;i<=3000;++i){
			if(otr[i].empty())continue;
			if(m==-1){
				m=i;
				sz=otr[i].size();cc=(*otr[i].begin()).c;
				continue;
			}
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m;
	LL cc;
	while(1){//to make num enough
		m=findm();
		if(m==-1)break;
		if(otr[m].empty())break;
		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc=0;
	while(1){
	    if(!ber.empty()){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);

	    }
	    else break;
		//get the cheapst
	    if(ntemp==(*all.begin()))break;
	    int fin=0;
		while(1){
			m=findm();
			if(m==-1){fin=1;break;}
			if((ber.size()+amt)<=otr[m].size()){
				ntemp=*all.begin();
				stemp.c=ntemp.c;
				stemp.p=ntemp.p;
				otr[ntemp.p].erase(ntemp);
				all.erase(ntemp);
				ber.insert(stemp);
				tprc+=stemp.c;
			}
			else break;
		}
		if(fin==1)break;
		if(tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c!=x.c?c<x.c:id<x.id;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
}ipt[3003];
set<np> otr[3003],all;

int vis[3003];

int main() {
	freopen("in.txt","r",stdin);
	int amt=0;
	scanf("%d %d", &n,&m);

	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		if(ipt[i].p==1){amt++;}
		else otr[ipt[i].p].insert(ipt[i]);
	}
	LL prc=LL(5+3e12),tprc=0,tot;
	set<np>::iterator iter;
	for(int t=0;t<n;++t){
		tot=amt;tprc=0;
		all.clear();
		for(int i=0;i<n;++i)if(ipt[i].p!=1)all.insert(ipt[i]);
		for(int j=2;j<=3000;++j){
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k){
					tot++;
					tprc+=(*iter).c;
					all.erase(*iter);
					iter++;
				}
			}
		}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()){
			tot++;
			tprc+=(*iter).c;
			iter++;
		}
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	if(prc==21){
		for(int t=0;t<n;++t)
			if(ipt[t].c<6)printf("%d %I64d\n",ipt[t].p,ipt[i].c);
	}
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

int findm(){//人最多，最小最小的集合
	int m=-1,sz=0;LL cc;
		for(int i=2;i<=n;++i){
			if(otr[i].empty())continue;
			if(m==-1){
				m=i;
				sz=otr[i].size();cc=(*otr[i].begin()).c;
				continue;
			}
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m=findm();
	LL cc;
	while(1){//to make num enough
		if(otr[m].empty())break;
		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
			m=findm();
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc=0;
	while(1){
	    if(!ber.empty()){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);

	    }
		//get the cheapst
		m=findm();
		while((ber.size()+amt)<=otr[m].size()){
			ntemp=*all.begin();
			stemp.c=ntemp.c;
			stemp.p=ntemp.p;
			otr[ntemp.p].erase(ntemp);
			all.erase(ntemp);
			ber.insert(stemp);
			tprc+=stemp.c;
			m=findm();
		}
		if(tprc>=prc)break;
		prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c!=x.c?c<x.c:id<x.id;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
}ipt[3003];
set<np> otr[3003],all;

int vis[3003];

int main() {
//	freopen("in.txt","r",stdin);
	int amt=0;
	scanf("%d %d", &n,&m);

	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		if(ipt[i].p==1){amt++;}
		else otr[ipt[i].p].insert(ipt[i]);
	}
	LL prc=LL(5+3e12),tprc=0,tot;
	set<np>::iterator iter;
	for(int t=0;t<n;++t){
		tot=amt;tprc=0;
		all.clear();
		for(int i=0;i<n;++i)if(ipt[i].p!=1)all.insert(ipt[i]);
		for(int j=2;j<=3000;++j){
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k){
					tot++;
					tprc+=(*iter).c;
					all.erase(*iter);
					iter++;
				}
			}
		}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()){
			tot++;
			tprc+=(*iter).c;
			iter++;
		}
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	if(prc==21){
		for(int t=0;t<n;++t)
			if(ipt[t].c<6)printf("%d %I64d\n",ipt[t].p,ipt[t].c);
	}
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

int findm(){//人最多，最小最小的集合
	int m=-1,sz=0;LL cc;
		for(int i=2;i<=3000;++i){
			if(otr[i].empty())continue;
			if(m==-1){
				m=i;
				sz=otr[i].size();cc=(*otr[i].begin()).c;
				continue;
			}
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m;
	LL cc;
	while(1){//to make num enough
		m=findm();
		if(m==-1)break;
		if(otr[m].empty())break;
		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc=0;
	while(1){
	    if(!ber.empty()){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);

	    }
		//get the cheapst
	    if(ntemp==(*all.begin()))break;
		while(1){
			m=findm();
			if(m==-1)break;
			if((ber.size()+amt)<=otr[m].size()){
				ntemp=*all.begin();
				stemp.c=ntemp.c;
				stemp.p=ntemp.p;
				otr[ntemp.p].erase(ntemp);
				all.erase(ntemp);
				ber.insert(stemp);
				tprc+=stemp.c;
			}
			else break;
		}
		if(tprc>prc)break;
		prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

int findm(){//人最多，最小最小的集合
	int m=-1,sz=0;LL cc;
		for(int i=2;i<=3000;++i){
			if(otr[i].empty())continue;
			if(m==-1){
				m=i;
				sz=otr[i].size();cc=(*otr[i].begin()).c;
				continue;
			}
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m;
	LL cc;
	while(1){//to make num enough
		m=findm();
		if(m==-1)break;
		if(otr[m].empty())break;
		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc=0;
	while(1){
	    if(!ber.empty()){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);

	    }
	    else break;
		//get the cheapst
	    if(ntemp==(*all.begin()))break;
	    int fin=0;
		while(1){
			m=findm();
			if(m==-1){fin=1;break;}
			if((ber.size()+amt)<=otr[m].size()){
				ntemp=*all.begin();
				stemp.c=ntemp.c;
				stemp.p=ntemp.p;
				otr[ntemp.p].erase(ntemp);
				all.erase(ntemp);
				ber.insert(stemp);
				tprc+=stemp.c;
			}
			else break;
		}
		if(fin==1)break;
		if(tprc>prc)break;
		prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
}ipt[3003];
set<np> otr[3003],all;

int vis[3003];

int main() {
	int amt=0;
	scanf("%d %d", &n,&m);
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		if(ipt[i].p==1)amt++;
		else otr[ipt[i].p].insert(ipt[i]);
	}
	LL prc=LL(5+3e12),tprc=0,tot;
	set<np>::iterator iter;
	for(int t=0;t<=n;++t){
		tot=amt;tprc=0;
		all.clear();
		for(int i=0;i<n;++i)all.insert(ipt[i]);
		for(int j=2;j<=m;++j){
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k){
					tot++;
					tprc+=(*iter).c;
					all.erase(*iter);
					iter++;
				}
			}
		}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()){
			tot++;
			tprc+=(*iter).c;
			iter++;
		}
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
}ipt[3003];
set<np> otr[3003],all;

int vis[3003];

int main() {
	int amt=0;
	scanf("%d %d", &n,&m);

	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		if(ipt[i].p==1){amt++;}
		else otr[ipt[i].p].insert(ipt[i]);
	}
	LL prc=LL(5+3e12),tprc=0,tot;
	set<np>::iterator iter;
	for(int t=0;t<=n;++t){
		tot=amt;tprc=0;
		all.clear();
		for(int i=0;i<n;++i)if(ipt[i].p!=1)all.insert(ipt[i]);
		for(int j=2;j<=m;++j){
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k){
					tot++;
					tprc+=(*iter).c;
					all.erase(*iter);
					iter++;
				}
			}
		}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()){
			tot++;
			tprc+=(*iter).c;
			iter++;
		}
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct sp{//已经支持的人
	int p;
	LL c;
	sp(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const sp& x)const{
		return c>x.c;
	}
};
set<sp> ber;

struct np{

	int p;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
};
set<np> otr[3003];
set<np>all;

int findm(){//人最多，最小最小的集合
	int m=-1,sz=0;LL cc;
		for(int i=2;i<=3000;++i){
			if(otr[i].empty())continue;
			if(m==-1){
				m=i;
				sz=otr[i].size();cc=(*otr[i].begin()).c;
				continue;
			}
			if(otr[i].size()>sz){
				sz=otr[i].size();m=i;cc=(*otr[i].begin()).c;
			}
			else if(otr[i].size()==sz&&(*otr[i].begin()).c<cc){
				m=i;cc=(*otr[i].begin()).c;
			}
		}
	return m;
}

int vis[3003];

int main() {
	int amt=0;LL prc=0;
	scanf("%d %d", &n,&m);
	np ntemp;sp stemp;
	int x;LL y;
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&x,&y);
		if(x==1)amt++;
		else {
			ntemp.p=x;ntemp.c=y;
			otr[x].insert(ntemp);
			all.insert(ntemp);
		}
	}
	int m=findm();
	LL cc;
	while(1){//to make num enough
		if(m==-1||otr[m].empty())break;
		if(amt+ber.size()<=otr[m].size()){
			ntemp=*otr[m].begin();
			ber.insert(sp(ntemp.p,ntemp.c));
			prc+=ntemp.c;
			otr[m].erase(ntemp);
			all.erase(ntemp);
			m=findm();
		}
		else break;
	}

	//now switch for cheaper ones
	LL tprc=0;
	while(1){
	    if(!ber.empty()){
		stemp=*ber.begin();//rip the most expensive
		tprc=prc-stemp.c;
		ntemp.p=stemp.p;ntemp.c=stemp.c;
		ber.erase(stemp);
		all.insert(ntemp);
		otr[ntemp.p].insert(ntemp);

	    }
		//get the cheapst
		m=findm();
		while((ber.size()+amt)<=otr[m].size()){
			ntemp=*all.begin();
			stemp.c=ntemp.c;
			stemp.p=ntemp.p;
			otr[ntemp.p].erase(ntemp);
			all.erase(ntemp);
			ber.insert(stemp);
			tprc+=stemp.c;
			m=findm();
		}
		if(tprc>=prc)break;
		prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id;
	LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}

	bool operator<(const np& x)const{
		return c<x.c;
	}
	bool operator==(const np&x)const{
		return c==x.c;
	}
}ipt[3003];
set<np> otr[3003],all;

int vis[3003];

int main() {
	int amt=0;
	scanf("%d %d", &n,&m);

	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		if(ipt[i].p==1){amt++;}
		else otr[ipt[i].p].insert(ipt[i]);
	}
	LL prc=LL(5+3e12),tprc=0,tot;
	set<np>::iterator iter;
	for(int t=0;t<=n;++t){
		tot=amt;tprc=0;
		all.clear();
		for(int i=0;i<n;++i)if(ipt[i].p!=1)all.insert(ipt[i]);
		for(int j=2;j<=3000;++j){
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k){
					tot++;
					tprc+=(*iter).c;
					all.erase(*iter);
					iter++;
				}
			}
		}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()){
			tot++;
			tprc+=(*iter).c;
			iter++;
		}
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


/*
codeforces 1020 C
写挂原因
为set重载<符号时，没有考虑当c相同时的顺序，
可能导致set认为两次插入的是相同的元素，只保留了一个导致答案错误
后增加了id的判断，保证每个元素都是不同的
*/
#include<stdio.h>
#include<set>
using std::set;
typedef long long LL;

int n,m;
struct np{
	int p,id; LL c;
	np(int _p=0,LL _c=0):p(_p),c(_c){}
	bool operator<(const np& x)const{ return c!=x.c?c<x.c:id<x.id;}
}ipt[3003];
set<np> otr[3003],all;

int main() {
	int amt=0; LL prc=LL(5+3e12),tprc=0,tot;
	scanf("%d %d", &n,&m);
	for (int i = 0; i <n; ++i) {
		scanf("%d %I64d",&ipt[i].p,&ipt[i].c);ipt[i].id=i+1;
		ipt[i].p==1?amt++:otr[ipt[i].p].insert(ipt[i]);
	}
	set<np>::iterator iter;
	for(int t=0;t<n;++t){
		tot=amt;tprc=0;all.clear();
		for(int i=0;i<n;++i)if(ipt[i].p!=1) all.insert(ipt[i]);
		for(int j=2;j<=3000;++j)
			if(otr[j].size()>t){
				iter=otr[j].begin();
				for(int k=t;k<otr[j].size();++k)
					tot++, tprc+=(*iter).c, all.erase(*iter), iter++;
			}
		iter=all.begin();
		while(tot<=t&&iter!=all.end()) tot++, tprc+=(*iter).c, iter++;
		if(tot>t&&tprc<prc)prc=tprc;
	}
	printf("%I64d\n",prc);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c,i;
}a[MAX];
ll b[MAX][MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			if(a[i].p==j){
				for(k=0;k<v[j].size();k++){
					if(a[i].c==v[j][k]&&b[j][k]==0){
						b[j][k]=1;
						a[i].i=k;
					}
				}
			}
		}
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].i>=v[a[i].p].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		if(v[1].size()+sumi>=k){
			ans=sum;
			break;
		}
		int f=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
					if(v[1].size()+sumi>=k){
						f=1;
						break;
					}
				}
				if(f==1) break;
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].c>v[i].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 1000000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<int> v[MAX];
struct Node{
	int p,c;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	int n,m,p,c,i,j,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%d%d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=2;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>k-1){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if(v[a[i].p].size()<k&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c,i;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		a[i].i=v[p].size();
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		if(v[1].size()+sumi>=k){
			ans=sum;
			break;
		}
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].i>=v[i].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 1000000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<int> v[MAX];
struct Node{
	int p,c;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	int n,m,p,c,i,j,k;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%d%d",&p,&c);
		a[i].p=p;
		if(p==1) a[i].c=1000000000;
		else a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=2;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>k-1){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if(v[a[i].p].size()<k){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].c>v[a[i].p][v[a[i].p].size()-(k-1)-1]))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
int b[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		memset(b,0,sizeof(b));
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					b[i]++;
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&b[a[i].p]<v[a[i].p].size()))&&a[i].p>1){
					b[a[i].p]++;
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
int b[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		memset(b,0,sizeof(b));
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					b[i]++;
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&b[a[i].p]-1<v[i].size()))&&a[i].p>1){
					b[a[i].p]++;
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c,i;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		a[i].i=v[p].size();
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].i>=v[i].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
int b[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		memset(b,0,sizeof(b));
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					b[i]++;
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&b[a[i].p]-1<v[a[i].p].size()))&&a[i].p>1){
					b[a[i].p]++;
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].c>v[i].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<algorithm>
#define MAX 3005
#define INF 10000000000000000
#define MOD 1000000007
using namespace std;
typedef long long ll;

vector<ll> v[MAX];
struct Node{
	ll p,c,i;
}a[MAX];
bool cmp(Node a,Node b){
	return a.c<b.c;
}
int main()
{
	ll n,m,p,c,i,j,k;
	scanf("%I64d%I64d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%I64d%I64d",&p,&c);
		a[i].p=p;
		a[i].c=c;
		a[i].i=v[p].size();
		v[p].push_back(c);
	}
	sort(a+1,a+n+1,cmp);
	for(i=1;i<=m;i++){
		sort(v[i].begin(),v[i].end());
	}
	ll ans=INF;
	for(k=n;k>=1;k--){
		ll sum=0,sumi=0;
		if(v[1].size()+sumi>=k){
			ans=sum;
			break;
		}
		for(i=2;i<=m;i++){
			if(v[i].size()>=k){
				for(j=0;j<v[i].size()-(k-1);j++){
					sum+=v[i][j];
					sumi++;
				}
			}
		}
		if(v[1].size()+sumi>=k){
			if(sum<ans) ans=sum;
		}
		else{
			for(i=1;i<=n;i++){
				if((v[a[i].p].size()<k||(v[a[i].p].size()>=k&&a[i].i>v[i].size()-(k-1)))&&a[i].p>1){
					sum+=a[i].c;
					sumi++;
					if(v[1].size()+sumi>=k) break;
				}
			}
			if(v[1].size()+sumi<k) continue;
			if(sum<ans) ans=sum;
		}
	}
	printf("%I64d\n",ans);
	return 0;
}


#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using std::sort;
const int maxn=3010;
int n,m,p,c,l[maxn],mx,sum=0,num=0;
long long mn=1e15;
std::vector<int> vp[maxn];
std::pair<int,int> v[maxn];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%d%d",&p,&c),
		vp[p].push_back(c),
		v[i] = std::make_pair(c,p);
	for(int i=1;i<=m;i++)
		if((l[i]=vp[i].size()))
			sort(vp[i].begin(),vp[i].end());
	sort(v,v+n);

	for(int vote=std::max(l[1],1);vote<=n;vote++){
		long long cost=0,cur=l[1],tot[maxn]={};
		for(int i=2,j;i<=m;i++){
			for(j=0;j+vote<=l[i];j++,cur++)
				cost+=vp[i][j];
			tot[i]+=j;
		}
		if(cur>vote) continue;
		if(cur<vote)
			for(int i=0;cur<vote&&i<n;i++){
				if(v[i].second==1) continue;
				if(tot[v[i].second]){
					tot[v[i].second]--;
					continue;
				}
				cost+=v[i].first,cur++;
			}
		mn=std::min(mn,cost);
	}
	std::cout<<mn<<std::endl;
}


#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using std::sort;
const int maxn=3010;
int n,m,p,c,l[maxn],mx,sum=0,num=0,mn,t=0;
std::vector<int> vp[maxn];
std::pair<int,int> v[maxn];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%d%d",&p,&c),
		vp[p].push_back(c),
		v[i] = std::make_pair(c,p);
	for(int i=1;i<=m;i++)
		if((l[i]=vp[i].size()))
			sort(vp[i].begin(),vp[i].end());
	sort(v,v+n);
	mn=maxn;

	for(int vote=std::max(l[1],1);vote<=n;vote++){
		int cost=0,cur=l[1],tot[maxn]={};
		for(int i=2,j;i<=m;i++){
			for(j=0;j+vote<=l[i];j++,cur++)
				cost+=vp[i][j];
			tot[i]+=j;
		}
		if(cur>vote) continue;
		if(cur<vote)
			for(int i=0;cur<vote&&i<n;i++){
				if(v[i].second==1) continue;
				if(tot[v[i].second]){
					tot[v[i].second]--;
					continue;
				}
				cost+=v[i].first,cur++;
			}
		mn=std::min(mn,cost);
	}
	printf("%d\n",mn);
}


#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using std::sort;
const int maxn=3010;
inline int min(int a,int b){return a>b?b:a;}
int n,m,p,c,l[maxn],mx,sum=0,num=0,mn,tmp[maxn]={};
std::vector<int> vp[maxn];
int ok(int vote){
	int cost=0,cur=0,tot=0;
	for(int i=1,j=0;i<=m;i++,j=0){
		if(i==1){
			cur+=l[i];
			continue;
		}
		for(j=0;j+vote<=l[i];j++,cur++)
			cost+=vp[i][j];
		for(;j<l[i];j++)
			tmp[tot++]=vp[i][j];
	}
	if(cur>vote) return maxn;
	if(cur<vote){
		sort(tmp,tmp+tot);
		for(int i=0;i+cur<vote;i++)
			cost+=tmp[i];
	}
	return cost;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%d%d",&p,&c),vp[p].push_back(c);
	for(int i=1;i<=m;i++)
		if((l[i]=vp[i].size()))
			sort(vp[i].begin(),vp[i].end());
			/*for(int j=0;j<=l[i];j++)
				sum[i][j]=(j?sum[i][j-1]+vp[i][j-1]:0);*/
	mn=maxn;
	for(int i=1;i<=n/2+1;i++)
		mn=min(mn,ok(i));
	printf("%d\n",mn);
}


#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using std::sort;
const int maxn=3010;
int n,m,p,c,l[maxn],mx,sum=0,num=0,mn,t=0;
std::vector<int> vp[maxn];
std::pair<int,int> v[maxn];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%d%d",&p,&c),
		vp[p].push_back(c),
		v[i] = std::make_pair(c,p);
	for(int i=1;i<=m;i++)
		if((l[i]=vp[i].size()))
			sort(vp[i].begin(),vp[i].end());
	sort(v,v+n);
	mn=maxn;

	for(int vote=std::max(l[1],1);vote<=n;vote++){
		int cost=0,cur=l[1],tot[maxn]={};
		for(int i=2,j;i<=m;i++){
			for(j=0;j+vote<=l[i];j++,cur++)
				cost+=vp[i][j];
			tot[i]+=j;
		}
		if(cur>vote) continue;
		if(cur<vote)
			for(int i=0;cur<vote&&i<n;i++){
				if(tot[v[i].second]||v[i].first==1){
					tot[v[i].second]--;
					continue;
				}
				cost+=v[i].first,cur++;
			}
		mn=std::min(mn,cost);
	}
	printf("%d\n",mn);
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 1 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
		}
		else if (parties[i].count == max)
		{
			maxCount++;
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{
			persons[p].isUsed = false;
			persons[p].id = p;
			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	int szPersons = p;

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	sort(persons, persons + szPersons, compare);

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (curMax == 1)
			break;

		if (curMax == -1)	//have at least two
		{
			totalCoin = totalCoin + persons[qa].coin;
			parties[1].count++;
			persons[qa].isUsed = true;
			parties[persons[qa].party].count--;
			parties[persons[qa].party].personCoin.pop_back();	//must the least
		}
		else
		{
			//������
			long long nextRound = 0;
			nextRound = persons[qa].coin + persons[qb].coin;

//			while (persons[qb].isUsed)	//����Ҫ�ж�Խ��
//				qb++;
//			nextRound = persons[qb].coin;

			int sz = parties[curMax].personCoin.size();
			long long nextLess = parties[curMax].personCoin[sz - 1].coin;

			if (nextLess < nextRound)
			{
				totalCoin = totalCoin + nextLess;
				parties[1].count++;
				int id = parties[curMax].personCoin[sz - 1].id;
				persons[id].isUsed = true;
				parties[curMax].count--;
				parties[curMax].personCoin.pop_back();	//must the least
			}
			else
			{
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count = parties[1].count + 1;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
				qa = qb;
//
//				persons[qb].isUsed = true;
//				parties[persons[qb].party].count--;
//				parties[persons[qb].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
		qb = qa + 1;
		while (qb < szPersons && persons[qb].isUsed)	//��Ҫ�ж�Խ�磿
			qb++;
	}

	printf("%I64d\n", totalCoin);

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;
std::vector<int> totalParty;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 2 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			totalParty.clear();
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
			totalParty.push_back(i);
		}
		else if (parties[i].count == max)
		{
			maxCount++;
			totalParty.push_back(i);
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{
			persons[p].isUsed = false;
			persons[p].id = p;
			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	int szPersons = p;

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	sort(persons, persons + szPersons, compare);

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (parties[1].count > parties[totalParty[0]].count)
			break;

		long long curMaxCount = parties[totalParty[0]].count;

		long long needLess = 0;
		for (int i = 0 ; i < totalParty.size() ; i++)
		{
			int sz = parties[totalParty[i]].personCoin.size();
			needLess = needLess + parties[totalParty[i]].personCoin[sz - 1].coin;
		}

		int needCount = curMaxCount - parties[1].count + 1;
		if (needCount > totalParty.size() + 1)
			needCount = totalParty.size() + 1;
		long long needRound = 0;
		int curCount = 0;
		std::vector<int> roundCount;
		for (int i = qa ; i < n ; i++)
		{
			if (persons[i].isUsed)
				continue;

			needRound = needRound + persons[i].coin;
			roundCount.push_back(i);

			curCount++;
			if (curCount >= needCount)
				break;
		}

		if (needLess < needRound)
		{
			totalCoin = totalCoin + needLess;
			parties[1].count = parties[1].count + totalParty.size();
			int q;
			int sz;
			for (int i = 0 ; i < totalParty.size() ; i++)
			{
				q = totalParty[i];
				sz = parties[q].personCoin.size();
				persons[parties[q].personCoin[sz - 1].party].isUsed = true;
				parties[q].count--;
				parties[q].personCoin.pop_back();	//must the least
			}
		}
		else
		{
//			totalCoin = totalCoin + needRound;
//			parties[1].count = parties[1].count + roundCount.size();

			for (int i = 0 ; i < roundCount.size() - 1 ; i++)
			{

				qa = roundCount[i];
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count++;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
		qb = qa + 1;
		while (persons[qb].isUsed)	//��Ҫ�ж�Խ�磿
			qb++;
	}

	printf("%I64d\n", totalCoin);

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;
std::vector<int> totalParty;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 2 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			totalParty.clear();
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
			totalParty.push_back(i);
		}
		else if (parties[i].count == max)
		{
			maxCount++;
			totalParty.push_back(i);
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{
			persons[p].isUsed = false;
			persons[p].id = p;
			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	int szPersons = p;

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	sort(persons, persons + szPersons, compare);

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (parties[1].count > parties[totalParty[0]].count)
			break;

		long long curMaxCount = parties[totalParty[0]].count;

		long long needLess = 0;
		for (int i = 0 ; i < totalParty.size() ; i++)
		{
			int sz = parties[totalParty[i]].personCoin.size();
			needLess = needLess + parties[totalParty[i]].personCoin[sz - 1].coin;
		}

		int needCount = curMaxCount - parties[1].count + 1;
		if (needCount > totalParty.size() + 1)
			needCount = totalParty.size() + 1;
		long long needRound = 0;
		int curCount = 0;
		std::vector<int> roundCount;
		for (int i = qa ; i < n ; i++)
		{
			if (persons[i].isUsed)
				continue;

			needRound = needRound + persons[i].coin;
			roundCount.push_back(i);

			curCount++;
			if (curCount >= needCount)
				break;
		}

		if (needLess < needRound)
		{
			totalCoin = totalCoin + needLess;
			parties[1].count = parties[1].count + totalParty.size();
			int q;
			int sz;
			for (int i = 0 ; i < totalParty.size() ; i++)
			{
				q = totalParty[i];
				sz = parties[q].personCoin.size();
				persons[parties[q].personCoin[sz - 1].party].isUsed = true;
				parties[q].count--;
				parties[q].personCoin.pop_back();	//must the least
			}
		}
		else
		{
//			totalCoin = totalCoin + needRound;
//			parties[1].count = parties[1].count + roundCount.size();
			int count = roundCount.size();
			if (count > 1)
				count--;

			for (int i = 0 ; i < count ; i++)
			{

				qa = roundCount[i];
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count++;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
	}

	printf("%I64d\n", totalCoin);

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;
std::vector<int> totalParty;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 2 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			totalParty.clear();
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
			totalParty.push_back(i);
		}
		else if (parties[i].count == max)
		{
			maxCount++;
			totalParty.push_back(i);
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{

//			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	if (p == 0)
	{
		printf("0\n");
		return 0;
	}

	int szPersons = p;
	sort(persons, persons + szPersons, compare);

	for (int i = 0 ; i < szPersons ; i++)
	{
		persons[i].isUsed = false;
		persons[i].id = i;
//		parties[persons[i].party].count++;
		parties[persons[i].party].personCoin.push_back(persons[i]);
	}

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (parties[1].count > parties[totalParty[0]].count)
			break;

		long long curMaxCount = parties[totalParty[0]].count;

		long long needLess = 0;
		for (int i = 0 ; i < totalParty.size() ; i++)
		{
			int sz = parties[totalParty[i]].personCoin.size();
			needLess = needLess + parties[totalParty[i]].personCoin[sz - 1].coin;
		}

		int needCount = curMaxCount - parties[1].count + 1;
		if (needCount > totalParty.size() + 1)
			needCount = totalParty.size() + 1;
		long long needRound = 0;
		int curCount = 0;
		std::vector<int> roundCount;
		for (int i = qa ; i < n ; i++)
		{
			if (persons[i].isUsed)
				continue;

			needRound = needRound + persons[i].coin;
			roundCount.push_back(i);

			curCount++;
			if (curCount >= needCount)
				break;
		}

		if (needLess < needRound)
		{
			totalCoin = totalCoin + needLess;
			parties[1].count = parties[1].count + totalParty.size();
			int q;
			int sz;
			for (int i = 0 ; i < totalParty.size() ; i++)
			{
				q = totalParty[i];
				sz = parties[q].personCoin.size();
				persons[parties[q].personCoin[sz - 1].id].isUsed = true;
				parties[q].count--;
				parties[q].personCoin.pop_back();	//must the least
			}
		}
		else
		{
//			totalCoin = totalCoin + needRound;
//			parties[1].count = parties[1].count + roundCount.size();
			int count = roundCount.size();
			if (count > 1)
				count--;

			for (int i = 0 ; i < count ; i++)
			{
				qa = roundCount[i];
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count++;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
	}

	printf("%I64d\n", totalCoin);

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;
std::vector<int> totalParty;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 2 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			totalParty.clear();
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
			totalParty.push_back(i);
		}
		else if (parties[i].count == max)
		{
			maxCount++;
			totalParty.push_back(i);
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{

//			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	int szPersons = p;
	sort(persons, persons + szPersons, compare);

	for (int i = 0 ; i < szPersons ; i++)
	{
		persons[i].isUsed = false;
		persons[i].id = i;
//		parties[persons[i].party].count++;
		parties[persons[i].party].personCoin.push_back(persons[i]);
	}

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (parties[1].count > parties[totalParty[0]].count)
			break;

		long long curMaxCount = parties[totalParty[0]].count;

		long long needLess = 0;
		for (int i = 0 ; i < totalParty.size() ; i++)
		{
			int sz = parties[totalParty[i]].personCoin.size();
			needLess = needLess + parties[totalParty[i]].personCoin[sz - 1].coin;
		}

		int needCount = curMaxCount - parties[1].count + 1;
		if (needCount > totalParty.size() + 1)
			needCount = totalParty.size() + 1;
		long long needRound = 0;
		int curCount = 0;
		std::vector<int> roundCount;
		for (int i = qa ; i < n ; i++)
		{
			if (persons[i].isUsed)
				continue;

			needRound = needRound + persons[i].coin;
			roundCount.push_back(i);

			curCount++;
			if (curCount >= needCount)
				break;
		}

		if (needLess < needRound)
		{
			totalCoin = totalCoin + needLess;
			parties[1].count = parties[1].count + totalParty.size();
			int q;
			int sz;
			for (int i = 0 ; i < totalParty.size() ; i++)
			{
				q = totalParty[i];
				sz = parties[q].personCoin.size();
				persons[parties[q].personCoin[sz - 1].id].isUsed = true;
				parties[q].count--;
				parties[q].personCoin.pop_back();	//must the least
			}
		}
		else
		{
//			totalCoin = totalCoin + needRound;
//			parties[1].count = parties[1].count + roundCount.size();
			int count = roundCount.size();
			if (count > 1)
				count--;

			for (int i = 0 ; i < count ; i++)
			{
				qa = roundCount[i];
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count++;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
	}

	printf("%I64d\n", totalCoin);

	return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>

using namespace std;

struct Person
{

	int id;
	int party;
	long long coin;
	bool isUsed;
};
Person persons[3010];

struct Party
{
	int id;
	int count;
	std::vector<Person> personCoin;
};
Party parties[3010];

int n, m;

bool compareNum(const Person &a, const Person &b)
{
	return a.coin > b.coin;
}

bool compare(const Person &a, const Person &b)
{
	if (a.coin == b.coin)
	{
		return parties[a.party].count > parties[b.party].count;
	}
	else
		return a.coin < b.coin;
}

long long totalCoin;

int getMax()
{
	int max = -2;
	int maxId;
	int maxCount = 0;
	for (int i = 1 ; i <= m ; i++)
	{
		if (parties[i].count > max)
		{
			max = parties[i].count;
			maxId = i;
			maxCount = 1;
		}
		else if (parties[i].count == max)
		{
			maxCount++;
		}
	}

	if (maxCount >= 2)
		return -1;	//����Ҫ����1����������
	else
		return maxId;
}

int main()
{
	scanf("%d%d", &n, &m);

	int total;
	int p = 0;
	for (int ii = 0 ; ii < n ; ii++)
	{
		scanf("%d%I64d", &(persons[p].party),
			&(persons[p].coin));

		parties[persons[p].party].count++;
		if (persons[p].party != 1)
		{
			persons[p].isUsed = false;
			persons[p].id = p;
			parties[persons[p].party].personCoin.push_back(persons[p]);
			p++;
		}
	}

	int szPersons = p;

	for (int i = 1 ; i <= m ; i++)
		sort(parties[i].personCoin.begin(), parties[i].personCoin.end(), compareNum);	//����

	sort(persons, persons + szPersons, compare);

	totalCoin = 0;
	int curMax;
	int qa = 0, qb = 1;	//һ��Ҳû���ù�
	while (1)
	{
		curMax = getMax();
		if (curMax == 1)
			break;

		if (curMax == -1)	//have at least two
		{
			totalCoin = totalCoin + persons[qa].coin;
			parties[1].count++;
			persons[qa].isUsed = true;
			parties[persons[qa].party].count--;
			parties[persons[qa].party].personCoin.pop_back();	//must the least
		}
		else
		{
			//������
			long long nextRound = 0;
			nextRound = persons[qa].coin + persons[qb].coin;

//			while (persons[qb].isUsed)	//����Ҫ�ж�Խ��
//				qb++;
//			nextRound = persons[qb].coin;

			int sz = parties[curMax].personCoin.size();
			long long nextLess = parties[curMax].personCoin[sz - 1].coin;

			if (nextLess < nextRound)
			{
				totalCoin = totalCoin + nextLess;
				parties[1].count++;
				int id = parties[curMax].personCoin[sz - 1].id;
				persons[id].isUsed = true;
				parties[curMax].count--;
				parties[curMax].personCoin.pop_back();	//must the least
			}
			else
			{
				totalCoin = totalCoin + persons[qa].coin;
				parties[1].count = parties[1].count + 1;
				persons[qa].isUsed = true;
				parties[persons[qa].party].count--;
				parties[persons[qa].party].personCoin.pop_back();	//must the least
				qa = qb;
//
//				persons[qb].isUsed = true;
//				parties[persons[qb].party].count--;
//				parties[persons[qb].party].personCoin.pop_back();	//must the least
			}
		}

		while (persons[qa].isUsed)	//����Ҫ�ж�Խ��
			qa++;
		qb = qa + 1;
		while (qb < szPersons && persons[qb].isUsed)	//��Ҫ�ж�Խ�磿
			qb++;
	}

	printf("%d\n", totalCoin);

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ll,int> pli;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
#define F first
#define S second
typedef vector<pli> vpli;
#define hell 1000000007
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define tests int t; cin>>t; while(t--)
#define take(a,b,c) for(b=0;b<c;b++) scanf("%d",&a[b]);
#define MAXN   1000001
typedef long long ll;
map<int,set<int> > mi;

int main(){

	int n,m,i,j,a,b;
	ll ans=0;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		cin>>a>>b;
		mi[a].insert(b);
	}
	int myvotes = mi[1].size();
	int highest = -1;
	for(i=2;i<=n;i++)
		highest=max(highest,int(mi[i].size()));
	while(myvotes<=highest)
	{
		ll highcost,lowcost;
		vector<int> high;
		for(i=2;i<=n;i++)
			if(mi[i].size()==highest)
				high.pb(i);
		highcost=0;
		for(i=0;i<high.size();i++)
			highcost+=*(mi[high[i]].begin());
		vector<pii> allvotes;
		for(i=2;i<=n;i++)
			for(set<int>::iterator it=mi[i].begin(); it!=mi[i].end(); it++ )
				allvotes.pb(mp(*it,i));
		sort(all(allvotes));
		if(highest==myvotes)
			highcost=LLONG_MAX;
		if(allvotes.size()<=high.size())
			lowcost=LLONG_MAX-1;
		else
			{
				lowcost=0;
				//sort(all(allvotes));
				for(i=0;i<=high.size();i++ )
					lowcost += allvotes[i].F;
			}
		if(highcost<=lowcost)
		{
			ans+=*(mi[high[0]].begin());
			myvotes++;
			//cout<<"high "<<high[0]<<endl;
			mi[high[0]].erase(mi[high[0]].begin());
		}
		else
		{
			myvotes++;
			//cout<<"low "<<allvotes[0].S<<endl;
			ans+=*(mi[allvotes[0].S].begin());
			mi[allvotes[0].S].erase(mi[allvotes[0].S].begin());
		}
		highest=-1;
		for(i=2;i<=n;i++)
			highest=max(highest,int(mi[i].size()));
	}
	cout<<ans;
	return 0;

}


#include<bits/stdc++.h>

using namespace std;
typedef long long int ll;

const int MAXN = 1e5 + 5, sqr = 350, t = MAXN / sqr + 1;
int n, a[MAXN], ans[MAXN], tmp[MAXN], fr[MAXN];
bool mark[MAXN];

bool check(int mid, int k){
	for(int i = 0; i < n; i++) mark[a[i]] = false;
	int cnt = 0, tt = 0;
	for(int j = 0; j < n; j++){
		if(mark[a[j]]) continue;
		if(cnt == mid){
			tt++;
			for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
			cnt = 0;
		}
		mark[a[j]] = true; tmp[cnt] = a[j]; cnt++;
	}
	tt++;
//	cout << "mid:" << mid << "   t:" << tt << '\n';
	if(tt > k) return false;
	return true;
}

int bs(int k){
	int l = 0, r = n+1, ans = -1;
	for(int h = 0; h < 20; h++){
		int mid = (l + r) / 2;
//		cout << "l:" << l << "  r:" << r << "   mid:" << mid << "   check:" << check(mid, k) << '\n';
		if(check(mid, k)){
			r = mid + 1;
			ans = mid;
		}
		else
			l = mid;
	}
	return ans;
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i++) cin >> a[i];
	for(int i = 1; i < sqr; i++){
		int cnt = 0;
		for(int j = 0; j < n; j++){
			if(mark[a[j]]) continue;
			if(cnt == i){
				ans[i]++;
				for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
				cnt = 0;
			}
			mark[a[j]] = true; tmp[cnt] = a[j]; cnt++;
		}
		ans[i]++;
		for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
	}
	////////// //n/sqrt
	for(int i = 1; i <= (n/sqr)+1; i++) fr[i] = bs(i);
	fr[0] = n+1;
	for(int i = 1; i <= (n/sqr)+1; i++)
		for(int j = fr[i]; j < fr[i - 1]; j++) ans[j] = i;
	for(int i = 1; i <= n; i++) cout << ans[i] << " ";
	cout << endl;
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long int ll;

const int MAXN = 1e5 + 5, sqr = 400, t = MAXN / sqr + 1;
int n, a[MAXN], ans[MAXN], tmp[MAXN], fr[MAXN];
bool mark[MAXN];

bool check(int mid, int k){
	for(int i = 0; i < n; i++) mark[a[i]] = false;
	int cnt = 0, tt = 0;
	for(int j = 0; j < n; j++){
		if(mark[a[j]]) continue;
		if(cnt == mid){
			tt++;
			for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
			cnt = 0;
		}
		mark[a[j]] = true; tmp[cnt] = a[j]; cnt++;
	}
	tt++;
//	cout << "mid:" << mid << "   t:" << tt << '\n';
	if(tt > k) return false;
	return true;
}

int bs(int k){
	int l = 0, r = n+1, ans = -1;
	for(int h = 0; h < 20; h++){
		int mid = (l + r) / 2;
//		cout << "l:" << l << "  r:" << r << "   mid:" << mid << "   check:" << check(mid, k) << '\n';
		if(check(mid, k)){
			r = mid + 1;
			ans = mid;
		}
		else
			l = mid;
	}
	return ans;
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i++) cin >> a[i];
	for(int i = 1; i < sqr; i++){
		int cnt = 0;
		for(int j = 0; j < n; j++){
			if(mark[a[j]]) continue;
			if(cnt == i){
				ans[i]++;
				for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
				cnt = 0;
			}
			mark[a[j]] = true; tmp[cnt] = a[j]; cnt++;
		}
		ans[i]++;
		for(int h = 0; h < cnt; h++) mark[tmp[h]] = false;
	}
	////////// //n/sqrt
	for(int i = 1; i <= (n/sqr)+1; i++) fr[i] = bs(i);
	fr[0] = n+1;
	for(int i = 1; i <= (n/sqr)+1; i++)
		for(int j = fr[i]; j < fr[i - 1]; j++) ans[j] = i;
	for(int i = 1; i <= n; i++) cout << ans[i] << " ";
	cout << endl;
	return 0;
}


#include<bits/stdc++.h>

using namespace std;
typedef long long int ll;

const int MAXN = 1e5 + 5;
int n, a[MAXN], seg[MAXN * 4], ans[MAXN], nxt[MAXN], mn[MAXN];
vector <int> qs[MAXN];

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

int get(int x, int b = 0, int e = n, int ind = 1){
	if(b + 1 == e)
		return b;
	int mid = (b + e) / 2;
	if(seg[ind*2] >= x)
		return get(x, b, mid, ind * 2);
	else{
		x -= seg[ind * 2];
		return get(x, mid, e, ind * 2 + 1);
	}
}

int main()
{
	ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i]; a[i]--;
		mn[i] = INT_MAX;
		qs[0].push_back(i+1);
	}
	for(int i = n-1; i >= 0; i--) nxt[i] = mn[a[i]], mn[a[i]] = i;
	for(int i = 0; i < n; i++)
		if(mn[a[i]] == i) //add(i);
			add(1, i);
	for(int i = 0; i < n; i++){
		for(auto k: qs[i]){
			ans[k]++;
			if(seg[1] <= k) continue;
			int ind = get(k+1);
			qs[ind].push_back(k);
		}
		add(-1, i);
		if(nxt[i] != INT_MAX) add(1, nxt[i]);
		//turn i off ->nxt i on !!intmax
	}
	for(int i = 0; i < n; i++)
		cout << ans[i+1] << " ";
	cout << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ff first
#define ss second
#define all(v) v.begin(),v.end()
#define pll pair<ll,ll>
#define sqr(x) (x)*(x)
#define mod 1000000007
#define mx 100002
#define block 320

ll n,k,tot;
ll a[mx],ans[mx],freq[block+2][mx];
ll l[block+2],r[block+2],sum[block+2],occur[mx];

void slow(ll x){
    memset(occur,-1,sizeof occur);
    ll cnt=0,ret=1;
    for(int i=1;i<=n;i++){
        if(occur[a[i]]!=ret){
            cnt++,occur[a[i]]=ret;
            if(cnt>x) occur[a[i]]=++ret,cnt=1;
        }
    }
    ans[x]=ret;
}

void precalc(){
    ll cnt=0;
    l[tot]=1;
    for(int i=1;i<=n;i++){
        if(!freq[tot][a[i]]){
            cnt++;
            if(cnt>k){
                r[tot]=i-1,sum[tot]=k;
                freq[++tot][a[i]]++;
                cnt=1,l[tot]=i;
            }
            else freq[tot][a[i]]++;
        }
        else freq[tot][a[i]]++;
    }
    r[tot]=n,sum[tot]=cnt;
    ans[k++]=tot+1;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(),cout.tie();
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(k=1;(k*k)<=n;k++) slow(k);
    precalc();
    for(;k<=n;k++){
        ll id=0;
        for(int i=1;i<=tot;i++){
            while(l[i]<=r[i]){
                if(!freq[id][a[l[i]]]){
                    if((sum[id]+1)>k) id++;
                    if(id==i) break;
                    sum[id]++;
                }
                freq[id][a[l[i]]]++;
                freq[i][a[l[i]]]--;
                if(!freq[i][a[l[i]]]) sum[i]--;
                r[id]++,l[i]++;
            }
        }
        ans[k]=id+1;
        tot=id;
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ff first
#define ss second
#define all(v) v.begin(),v.end()
#define pll pair<ll,ll>
#define sqr(x) (x)*(x)
#define mod 1000000007
#define mx 100002
#define block 320

ll n,k,tot;
ll a[mx],ans[mx],freq[block+2][mx];
ll l[block+2],r[block+2],sum[block+2],occur[mx];

void slow(ll x){
    memset(occur,-1,sizeof occur);
    ll cnt=0,ret=1;
    for(int i=1;i<=n;i++){
        if(occur[a[i]]!=ret){
            cnt++,occur[a[i]]=ret;
            if(cnt>x) occur[a[i]]=++ret,cnt=1;
        }
    }
    ans[x]=ret;
}

void precalc(){
    ll cnt=0;
    l[tot]=1;
    for(int i=1;i<=n;i++){
        if(!freq[tot][a[i]]){
            cnt++;
            if(cnt>k){
                r[tot]=i-1,sum[tot]=k;
                freq[++tot][a[i]]++;
                cnt=1,l[tot]=i;
            }
            else freq[tot][a[i]]++;
        }
        else freq[tot][a[i]]++;
    }
    r[tot]=n,sum[tot]=cnt;
    ans[k++]=tot+1;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(),cout.tie();
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(k=1;(k*k)<=n;k++) slow(k);
    precalc();
    for(;k<=n;k++){
        ll id=0;
        for(int i=1;i<=tot;i++){
            while(l[i]<=r[i]){
                if(!freq[id][a[l[i]]]){
                    if((sum[id]+1)>k) id++;
                    if(id==i) break;
                    sum[id]++;
                }
                freq[id][a[l[i]]]++;
                freq[i][a[l[i]]]--;
                if(!freq[i][a[l[i]]]) sum[i]--;
                r[id]++,l[i]++;
            }
        }
        for(int i=id+1;i<=tot;i++){
            while(l[i]<=r[i]){
                if(!freq[id][a[l[i]]]){
                    if((sum[id]+1)>k) id++;
                    if(id==i) break;
                    sum[id]++;
                }
                freq[id][a[l[i]]]++;
                freq[i][a[l[i]]]--;
                if(!freq[i][a[l[i]]]) sum[i]--;
                r[id]++,l[i]++;
            }
        }
        ans[k]=id+1;
        tot=id;
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define ff first
#define ss second
#define all(v) v.begin(),v.end()
#define pll pair<ll,ll>
#define sqr(x) (x)*(x)
#define mod 1000000007
#define mx 100002
#define block 320

ll n,k,tot;
ll a[mx],ans[mx],freq[block+2][mx];
ll l[block+2],r[block+2],sum[block+2],occur[mx];

void slow(ll x){
    memset(occur,-1,sizeof occur);
    ll cnt=0,ret=1;
    for(int i=1;i<=n;i++){
        if(occur[a[i]]!=ret){
            cnt++,occur[a[i]]=ret;
            if(cnt>x) occur[a[i]]=++ret,cnt=1;
        }
    }
    ans[x]=ret;
}

void precalc(){
    ll cnt=0;
    l[tot]=1;
    for(int i=1;i<=n;i++){
        if(!freq[tot][a[i]]){
            cnt++;
            if(cnt>k){
                r[tot]=i-1,sum[tot]=k;
                freq[++tot][a[i]]++;
                cnt=1,l[tot]=i;
            }
            else freq[tot][a[i]]++;
        }
        else freq[tot][a[i]]++;
    }
    r[tot]=n,sum[tot]=cnt;
    ans[k]=tot+1,k++;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(),cout.tie();
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(k=1;(k*k)<=n;k++) slow(k);
    precalc();
    for(;k<=n;k++){
        ll id=0,cur=1;
        for(int i=1;i<=tot;i++){
            while(l[i]<=r[i]){
                if(!freq[id][a[l[i]]]){
                    if((sum[id]+1)>k) id++;
                    if(id==i) break;
                    sum[id]++;
                    if(r[id]<cur) l[id]=l[i],r[id]=l[i]-1;
                }
                freq[id][a[l[i]]]++;
                freq[i][a[l[i]]]--;
                if(!freq[i][a[l[i]]]) sum[i]--;
                r[id]++,l[i]++,cur=r[id];
            }
        }
        ans[k]=id+1;
        tot=id;
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    cout<<endl;
    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< lo,lo > 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 ((l+r)/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;
int cev;
string s;
map<PII,int> visit;
vector<int> v;

inline int naivesol(int m){
	int grup=1;
	visit.clear();
	cev=0;
	FOR{
		if(cev==m && visit[mp(grup,a[i])]==0){grup++;cev=0;}
		visit[mp(grup,a[i])]++;
		if(visit[mp(grup,a[i])]==1)cev++;
	}
	//~ cout<<m<<"()()"<<endl;
	return grup;
}

inline void dac(int l,int r,int optl,int optr){
	if(l>r)return ;
	if(optl==optr)b[ort]=optl;
	//~ cout<<"**\n";
	if(b[ort]==-1)b[ort]=naivesol(ort);
	dac(l,ort-1,optl,b[ort]),dac(ort+1,r,b[ort],optr);
}

int main(void){
	memset(b,-1,sizeof(b));
	scanf("%d",&n);
	FOR{
		scanf("%d",&a[i]);
	}
	dac(1,n,-inf,inf);
	FOR printf("%d ",b[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< lo,lo > 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 ((l+r)/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;
int cev;
string s;
map<PII,int> visit;
vector<int> v;

inline int naivesol(int m){
	int grup=1;
	visit.clear();
	cev=0;
	FOR{
		if(cev==m && visit[mp(grup,a[i])]==0){grup++;cev=0;}
		visit[mp(grup,a[i])]++;
		if(visit[mp(grup,a[i])]==1)cev++;
	}
	//~ cout<<m<<"()()"<<endl;
	return grup;
}

inline void dac(int l,int r,int optl,int optr){
	if(l>r)return ;
	if(optl==optr)b[ort]=optl;
	//~ cout<<"**\n";
	if(b[ort]==-1)b[ort]=naivesol(ort);
	dac(l,ort-1,optl,max(optr,b[ort])),dac(ort+1,r,min(b[ort],optl),optr);
}

int main(void){
	memset(b,-1,sizeof(b));
	scanf("%d",&n);
	FOR{
		scanf("%d",&a[i]);
	}
	dac(1,n,inf,-inf);
	FOR printf("%d ",b[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< lo,lo > 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 ((l+r)/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,vis[li];
int cev;
string s;
//~ map<PII,int> visit;
vector<int> v;

inline int naivesol(int m){
	int grup=1;
	memset(vis,0,sizeof(vis));
	cev=0;
	FOR{
		if(cev==m && vis[a[i]]!=grup){grup++;cev=0;}
		if(vis[a[i]]!=grup)cev++;
		vis[a[i]]=grup;

	}
	//~ cout<<m<<"()()"<<endl;
	return grup;
}

inline void dac(int l,int r,int optl,int optr){
	if(l>r)return ;
	if(optl==optr)b[ort]=optl;
	//~ cout<<"**\n";
	if(b[ort]==-1)b[ort]=naivesol(ort);
	dac(l,ort-1,optl,b[ort]),dac(ort+1,r,b[ort],optr);
}

int main(void){
	memset(b,-1,sizeof(b));
	scanf("%d",&n);
	FOR{
		scanf("%d",&a[i]);
	}
	dac(1,n,-inf,inf);
	FOR printf("%d ",b[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< lo,lo > 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 ((l+r)/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;
int cev;
string s;
map<PII,int> visit;
vector<int> v;

inline int naivesol(int m){
	int grup=1;
	visit.clear();
	cev=0;
	FOR{
		if(cev==m && visit[mp(grup,a[i])]==0){grup++;cev=0;}
		visit[mp(grup,a[i])]++;
		if(visit[mp(grup,a[i])]==1)cev++;
	}
	//~ cout<<m<<"()()"<<endl;
	return grup;
}

inline void dac(int l,int r,int optl,int optr){
	if(l>r)return ;
	if(optl==optr)b[ort]=optl;
	//~ cout<<"**\n";
	if(b[ort]==-1)b[ort]=naivesol(ort);
	dac(l,ort-1,optl,b[ort]),dac(ort+1,r,b[ort],optr);
}

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


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

struct StVal {
	int value = 0;
	StVal *left, *right;
	StVal() {}
	StVal(const int _v) : value(_v) { left = right = NULL; }
	StVal(StVal* v1, StVal* v2) {
		value = *v1 + *v2;
		left = v1; right = v2;
	}
	operator int() const { return value; }
};

struct PSSegTree {
	int n;
	vector<StVal*> versions;	//contains the root of each version
	vector<StVal*> st;	//st[1] is the root

	PSSegTree(const int n) : n(n) { init(1, 0, n - 1); versions.push_back(st[1]); }

	void init(const int si, const int lo, const int hi) {
		if (lo == hi) {
			if (si >= (int)st.size()) st.resize(si + 1);
			st[si] = new StVal();
		}
		else {
			const int mid = (lo + hi) >> 1;
			init(si << 1, lo, mid);
			init(si << 1 | 1, mid + 1, hi);
			st[si] = new StVal(st[si << 1], st[si << 1 | 1]);
		}
	}

	//l and r inclusive, 0-indexed, version v
	StVal* queryS(const int l, const int r, const int v = 0) {
		return (l <= r && l < n && r >= 0) ? queryS(l, r, versions[v], 0, n - 1) : new StVal();
	}
	StVal* queryS(const int l, const int r, StVal* si, const int lo, const int hi) {
		if (l <= lo && hi <= r) return si;

		const int mid = (lo + hi) >> 1;
		if (r <= mid) return queryS(l, r, si->left, lo, mid);
		if (mid < l) return queryS(l, r, si->right, mid + 1, hi);
		return new StVal(queryS(l, r, si->left, lo, mid), queryS(l, r, si->right, mid + 1, hi));
	}

	int query(int k, const int v = 0) { return query(k, versions[v], 0, n - 1); }
	int query(int k, StVal* si, const int lo, const int hi) {
		if (k > si->value) { return n; }
		if (lo == hi) { return lo; }

		const int mid = (lo + hi) >> 1;
		if (si->left->value < k) { return query(k - si->left->value, si->right, mid + 1, hi); }
		else { return query(k, si->left, lo, mid); }
	}

	//PERSISTENT UPDATE
	//v version, i idx, nx new val
	StVal* PSUpdate(int v, int i, int nx) { return PSUpdate(v, 0, n - 1, i, nx, versions[v]); }
	StVal* PSUpdate(int v, int l, int r, int i, int nx, StVal* cur) {
		if (l == r) {
			StVal* nv = new StVal(nx);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
		if (l == r - 1) {
			StVal* nv = new StVal(nx), *par;
			if (i == l) { par = new StVal(nv, cur->right); }
			else { par = new StVal(cur->left, nv); }
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return par;
		}
		int m = (l + r) >> 1;
		if (i <= m) {
			StVal* nl = PSUpdate(v, l, m, i, nx, cur->left);
			StVal* nv = new StVal(nl, cur->right);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
		else {
			StVal* nr = PSUpdate(v, m + 1, r, i, nx, cur->right);
			StVal* nv = new StVal(cur->left, nr);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
	}
};

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

	int n; cin >> n;
	vector<int> nums(n);
	for (auto &x : nums) { cin >> x; }

	vector<int> occ(n + 1, -1), ltov(n);
	PSSegTree st(n); int v = 0;
	for (int i = n - 1; i >= 0; i--) {
		if (occ[nums[i]] != -1) {
			st.PSUpdate(v, occ[nums[i]], 0); v++;
		}
		st.PSUpdate(v, i, 1); v++;

		occ[nums[i]] = i; ltov[i] = v;
	}

	for (int k = 1; k <= n; k++) {
		int l = 0, res = 0;
		while (l < n) {
			int bef = st.queryS(0, l - 1, ltov[l])->value;
			int r = st.query(bef + k + 1, ltov[l]); r--;
			res++; l = r + 1;
		}
		cout << res << ' ';
	}
	cout << '\n';
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;

struct StVal {
	int value = 0;
	StVal *left, *right;
	StVal() {}
	StVal(const int _v) : value(_v) { left = right = NULL; }
	StVal(StVal* v1, StVal* v2) {
		value = *v1 + *v2;
		left = v1; right = v2;
	}
	operator int() const { return value; }
};

struct PSSegTree {
	int n;
	vector<StVal*> versions;	//contains the root of each version
	vector<StVal*> st;	//st[1] is the root

	PSSegTree(const int n) : n(n) { init(1, 0, n - 1); versions.push_back(st[1]); }

	void init(const int si, const int lo, const int hi) {
		if (lo == hi) {
			if (si >= (int)st.size()) st.resize(si + 1);
			st[si] = new StVal();
		}
		else {
			const int mid = (lo + hi) >> 1;
			init(si << 1, lo, mid);
			init(si << 1 | 1, mid + 1, hi);
			st[si] = new StVal(st[si << 1], st[si << 1 | 1]);
		}
	}

	//l and r inclusive, 0-indexed, version v
	StVal* queryS(const int l, const int r, const int v = 0) {
		return (l <= r && l < n && r >= 0) ? queryS(l, r, versions[v], 0, n - 1) : new StVal();
	}
	StVal* queryS(const int l, const int r, StVal* si, const int lo, const int hi) {
		if (l <= lo && hi <= r) return si;

		const int mid = (lo + hi) >> 1;
		if (r <= mid) return queryS(l, r, si->left, lo, mid);
		if (mid < l) return queryS(l, r, si->right, mid + 1, hi);
		return new StVal(queryS(l, r, si->left, lo, mid), queryS(l, r, si->right, mid + 1, hi));
	}

	int query(int k, const int v = 0) { return query(k, versions[v], 0, n - 1); }
	int query(int k, StVal* si, const int lo, const int hi) {
		if (k > si->value) { return n; }
		if (lo == hi) { return lo; }

		const int mid = (lo + hi) >> 1;
		if (si->left->value < k) { return query(k - si->left->value, si->right, mid + 1, hi); }
		else { return query(k, si->left, lo, mid); }
	}

	//PERSISTENT UPDATE
	//v version, i idx, nx new val
	StVal* PSUpdate(int v, int i, int nx) { return PSUpdate(v, 0, n - 1, i, nx, versions[v]); }
	StVal* PSUpdate(int v, int l, int r, int i, int nx, StVal* cur) {
		if (l == r) {
			StVal* nv = new StVal(nx);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
		if (l == r - 1) {
			StVal* nv = new StVal(nx), *par;
			if (i == l) { par = new StVal(nv, cur->right); }
			else { par = new StVal(cur->left, nv); }
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return par;
		}
		int m = (l + r) >> 1;
		if (i <= m) {
			StVal* nl = PSUpdate(v, l, m, i, nx, cur->left);
			StVal* nv = new StVal(nl, cur->right);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
		else {
			StVal* nr = PSUpdate(v, m + 1, r, i, nx, cur->right);
			StVal* nv = new StVal(cur->left, nr);
			if (l == 0 && r == n - 1) { versions.push_back(nv); }
			return nv;
		}
	}
};

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

	int n; cin >> n;
	vector<int> nums(n);
	for (auto &x : nums) { cin >> x; }

	vector<int> occ(n + 1, -1), ltov(n);
	PSSegTree st(n); int v = 0;
	for (int i = n - 1; i >= 0; i--) {
		if (occ[nums[i]] != -1) {
			st.PSUpdate(v, occ[nums[i]], 0); v++;
		}
		st.PSUpdate(v, i, 1); v++;

		occ[nums[i]] = i; ltov[i] = v;
	}

	for (int k = 1; k <= n; k++) {
		int l = 0, res = 0;
		while (l < n) {
			int r = st.query(k + 1, ltov[l]); r--;
			res++; l = r + 1;
		}
		cout << res << ' ';
	}
	cout << '\n';
}


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

struct node{

	int sum;
	node *left, *right;

	node() {
		sum = 0;
		left = right = this;
	}

	node(int s, node *l = new node, node *r = new node) {
		sum = s;
		left = l;
		right = r;
	}
};

node *insert(node *root, int i, int val, int lx = 1, int rx = 100000) {
	if(i < lx || i > rx)
		return root;
	if(lx == rx){
		return new node(val);
	}
	int mid = (lx + rx) / 2;
	node *ln = insert(root -> left, i, val, lx, mid);
	node *rn = insert(root -> right, i, val, mid + 1, rx);
	return new node(ln -> sum + rn -> sum, ln, rn);
}

int query(node *root, int s, int lx = 1, int rx = 100000) {
	if (lx == rx)
		return lx;
	int mid = (lx + rx) / 2;
	if(root -> left -> sum >= s)
		return query(root -> left, s, lx, mid);
	return query(root -> right, s - root -> left -> sum, mid + 1, rx);
}

int main(){

	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n, val;
    cin >> n;
    node *roots[n + 1];
    roots[0] = new node;
	vector < int > last(n + 1);
	for(int i = 1; i <= n; i++) {
		cin >> val;
		roots[i] = insert(roots[i - 1], i, 1);
		if(last[val] != 0)
			roots[i] = insert(roots[i], last[val], 0);
		last[val] = i;
	}
	for(int i = 1; i <= n; i++) {
		int res = 1, idx = n;
		while ((roots[idx] -> sum) > i) {
			idx = query(roots[idx], roots[idx] -> sum - i);
			res++;
		}
		cout << res << " ";
	}

    return 0;


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

struct node{

	int sum;
	node *left, *right;

	node() {
		sum = 0;
		left = right = this;
	}

	node(int s, node *l = new node, node *r = new node) {
		sum = s;
		left = l;
		right = r;
	}
};

node *insert(node *root, int i, int val, int lx = 1, int rx = 100000) {
	if(i < lx || i > rx)
		return root;
	if(lx == rx){
		return new node(val);
	}
	int mid = (lx + rx) / 2;
	node *ln = insert(root -> left, i, val, lx, mid);
	node *rn = insert(root -> right, i, val, mid + 1, rx);
	return new node(ln -> sum + rn -> sum, ln, rn);
}

int query(node *root, int s, int lx = 1, int rx = 100000) {
	if (lx == rx)
		return lx;
	int mid = (lx + rx) / 2;
	if(root -> left -> sum >= s)
		return query(root -> left, s, lx, mid);
	return query(root -> right, s - root -> left -> sum, mid + 1, rx);
}

int main(){

	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int n, val;
    cin >> n;
    node *roots[n + 1];
    roots[0] = new node;
	vector < int > last(n + 1);
	for(int i = 1; i <= n; i++) {
		cin >> val;
		roots[i] = insert(roots[i - 1], i, 1);
		if(last[val] != 0)
			roots[i] = insert(roots[i], last[val], 0);
		last[val] = i;
	}
	for(int i = 1; i <= n; i++) {
		int res = 1, idx = n;
		while ((roots[idx] -> sum) > i) {
			idx = query(roots[idx], roots[idx] -> sum - i);
			res++;
		}
		cout << res << " ";
	}

    return 0;
}


#include <bits/stdc++.h>
#define vi vector<int>
using namespace std;
int n;
const int N=100005;
int a[N],R[N],ar[N];
template<typename T>
inline void SI(T &n)
{
    char c=getchar();
    for (n=0; (c>47 && c<58); c=getchar())n=10*n+c-48;
}
int f(int e){
    memset(ar,-1, sizeof ar);
    int r=0,c=0;
    for(int j=1;j<=n;j++){
        if(ar[a[j]]==r)continue;
        ar[a[j]]=r;
        c++;
        if(c>e){
            c=1;r++;ar[a[j]]=r;
        }
    }
    return r;
}
void F(int l,int r){
    if(l>r)return ;
    R[l]=f(l);
    R[r]=f(r);
    if(R[l]==R[r]){
        for(int i=l+1;i<r;i++)R[i]=R[l];
        return;
    }
    F(l+1,(l+r)/2);
    F((l+r)/2+1,r-1);
}
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    SI(n);
    for(int i=1;i<=n;i++)SI(a[i]);
    F(1,n);
    for(int i=1;i<=n;i++)printf("%d ",R[i]);
    return 0;
}


#include <bits/stdc++.h>
#define vi vector<int>
using namespace std;
int n;
const int N=100005;
int a[N],R[N],ar[N];
template<typename T>
inline void SI(T &n)
{
    char c=getchar();
    for (n=0; (c>47 && c<58); c=getchar())n=10*n+c-48;
}
int f(int e){
    memset(ar,-1, sizeof ar);
    int r=0,c=0;
    for(int j=1;j<=n;j++){
        if(ar[a[j]]==r)continue;
        ar[a[j]]=r;
        c++;
        if(c>e){
            c=1;r++;ar[a[j]]=r;
        }
    }
    return r;
}
void F(int l,int r){
    if(l>r)return ;
    R[l]=f(l);
    R[r]=f(r);
    if(R[l]==R[r]){
        for(int i=l+1;i<r;i++)R[i]=R[l];
        return;
    }
    F(l+1,(l+r)/2);
    F((l+r)/2+1,r-1);
}
int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    SI(n);
    for(int i=1;i<=n;i++)SI(a[i]);
    F(1,n);
    for(int i=1;i<=n;i++)printf("%d ",R[i]+1);
    return 0;
}


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

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

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

/*

*/

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


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

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

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

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

/*

*/

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