洛谷P4447分组 题解

题目传送门

看到此题,第一个想法:仿桶排序!

于是就这样做。

输入是:0 1 2 2 3 3 3 4

数组键值表:

0 1 2 3 4

1 1 2 3 1

碰到值大于0,就开始分组,一口气分到不能再分为止。这个案例,分组就是:

0 1 2 3 4
2 3
3

emmm…不对啊,正确答案是2

0 1 2 3
2 3
3 4

那怎么办?!!第一次分组时应该只分到3,刚好这个值在3的时候第一次下降。

考虑在数量第一次下降时停止分组。

#include<iostream>
using namespace std;
short int es[2000000078];
int main(){
	int n,a=2e9;cin>>n;
	for(int i=0;i<n;i++){
		int f;cin>>f;
		es[f+(int)1e9]++;
	}
	while(1){
		int m,q=0;
		for(m=0;!es[m]&&m<=2e9+10;m++);
		if(m>2e9)break;
		for(;es[m]<=es[m+1];m++,q++)es[m]--;
		es[m]--;
		a=min(a,q+1);
	}
	cout<<a<<endl;
}

结果惨不忍睹

$\color{white} WTF?!$

果然是内存不足了,早知道我就不开那么大的数组 结果60分

emmm…后来就想到了用map

用iterator来遍历,还是上面的思路,但是要记住最后如果降为0要把它erase掉

贴代码:

#include<iostream>
#include<map>
using namespace std;
map<int,int>es;
int main(){
	int n,a=2e9;cin>>n;
	for(int i=0;i<n;i++){
		int f;cin>>f;
		es[f]++;
	}
	while(!es.empty()){
		int q=1;
		map<int,int>::iterator m=es.begin();
		int sm=(*m).first;
		for(;es[sm]<=es[sm+1];sm++,q++)es[sm]--;
		es[sm]--;
		a=min(a,q);
		while(m!=es.end()&&(*m).second==0)es.erase((*m++).first);
	}
	cout<<a<<endl;
}