Codeforces 1077D Cutting Out

网址:http://codeforces.com/contest/1077/problem/D
题面的意思是让你在长度n的数组中选出k个可以重复的数,这k个可以重复的数的组合在原数组中出现的次数t最大,输出选择方案。题面比较绕,一定要好好看举的例子。
可以发现,对于所有数字按照出现频率排序以后,优先选择出现次数多的数是肯定没有问题的。但是有些出现次数多的数可以多次选择,这个题就变的比较麻烦。我们发现,如果对于给定的t,可以在O(n)时间算出答案,并且t具有单调性(如果一个数组可以重复5次,就一定可以重复4次3次2次。一个数组不能重复5次,就肯定不能重复6次7次8次)。所以我们可以对t进行二分。这样这道题就结束了。

#include <cstdio>
#include <map>
#include <algorithm>
#include <cstring>

using namespace std;

const int N=200005;

struct Num{
	int time,val;
}nums[N];

int k,n,a[N],cnt=0,b[N],ans[N],cnt2=0;
map<int,int> m;

bool operator<(Num a,Num b) {
	return a.time>b.time;	
}

int main(void) {
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;++i) {
		scanf("%d",a+i);
		if (m.count(a[i]))
			++m[a[i]];
		else
			m[a[i]]=1;
	} 
	for (auto it=m.begin();it!=m.end();++it) {
		nums[cnt].time=it->second;
		nums[cnt++].val=it->first;
	}
	sort(nums,nums+cnt);
	int l=1,r=n,t=0;
	while (l<=r) {
		t=(l+r)>>1;
		cnt2=0;
		for (int i=0;i<cnt;++i) {
			for (int j=0;j<nums[i].time/t;++j)
				b[cnt2++]=nums[i].val;
			if (cnt2>=k)
				break;	
		}
		if (cnt2>=k) {
			l=t+1;
			memcpy(ans,b,k*sizeof(int));
		} else
			r=t-1;
	}
	for (int i=0;i<k;++i)
		printf((i==k-1)?"%d\n":"%d ",ans[i]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值