D. Cutting Out (二分查找) Codeforces Round #521 (Div. 3)
原题链接: https://codeforces.com/contest/1077/problem/D
测试样例:
Examples
Input
7 3
1 2 3 2 4 3 1
Output
1 2 3
Input
10 4
1 3 1 3 10 3 7 7 12 3
Output
7 3 1 3
Input
15 2
1 2 1 1 1 2 1 1 2 1 2 1 1 1 1
Output
1 1
Note
The first example is described in the problem statement.
In the second example the only answer is [7,3,1,3] and any its permutations. It can be shown that you cannot choose any other array such that the maximum number of copies you can cut out would be equal to 2.
In the third example the array t can be cut out 5 times.
题意: 给你一个长度为 n n n的数组 s s s,要求你找到一个长为 k k k的数组 t t t,使得从 s s s中删去最多的 t t t。
解题思路: 对于这个题目,我们会发现我们的删除次数会和数组
s
s
s中的
t
t
t数组中数字出现次数有关,我们要组成
t
t
t数组必然是选择出现次数最多的。那么也跟
t
t
t数组的长度有关,这个长度也同样影响着我们删除次数的值。那么不管别的,我们删除次数最少是
1
1
1次,最大是
n
n
n次。对于我们的输入数据,我们所产生的的最大删除次数必然是在其中,所以我们也固然是要找到这个值,那么为了提高效率,这里我们采用二分法搜索,同样,对于每个值你必须设置
c
h
e
c
k
check
check函数来检查该值是否有效,找到最大删除次数后自然可以遍历一遍数组输出我们能够删除的数字,知道长度达到
k
k
k。具体看代码。
AC代码:
/*
*邮箱:unique_powerhouse@qq.com
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*/
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 2e5+4;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int n,k,cnt[maxn];
//判断该删除次数是否可行
bool check(int mid,int k){
int sum=0;
rep(i,1,maxn-1){
if(cnt[i]>=mid){
sum+=cnt[i]/mid;
}
if(sum>=k)
return true;
}
return false;
}
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>n>>k){
int temp;
memset(cnt,0,sizeof(cnt));//初始化
rep(i,0,n-1){
cin>>temp;
cnt[temp]++;//统计出现次数。
}
int l=1,r=n,mid,result=0;
//我们用二分法寻找最大删除次数。
while(l<=r){
mid=(l+r)>>1;
if(check(mid,k)){
result=mid;
l=mid+1;
}
else{
r=mid-1;
}
}
//已经找到最大删除次数,开始输出即可。
rep(i,1,maxn-1){
if(cnt[i]>=result){
temp=cnt[i]/result;
while(temp--){
cout<<i<<" ";
k--;
if(k==0){
cout<<endl;
break;
}
}
if(k==0)
break;
}
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!