题意
有n个工人和m个任务。每个任务都应该有一个工人分配给它。如果一个工人精通该任务,他们就会在1小时内完成。否则,他们需要2小时。
工人们平行工作,彼此独立。每个工人一次只能做一个任务。
将工人分配到所有的任务中,使任务尽可能早地完成。工作从时间0开始,所有的任务最短可以在什么时候完成?
输入
第一行输入数据组数t.
每组数据第一行为n,m,接下来输入m个整数,
a
i
a_{i}
ai表示精通第i项任务的工人.
输出
完成所有任务所需的最小时间
思路
二分答案,check()判断答案是否可行.假设n项任务需要n个劳动力.如果一个工人精通该任务,那么可以贡献1个单位的劳动力,否则就只能共享1/2个单位的劳动力,最后判断所需的劳动力是否小于所贡献的劳动力即可判断枚举的时间内能否完成所有任务.
代码
#include<iostream>
#include<algorithm>
#include<vector>
#define endl "\n"
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pii=pair<int,int>;
const int N=2e5+5;
int n,m,a[N];
void slove(){
cin>>n>>m;
vector<int> cnt(N,0);
for(int i=1;i<=m;i++){
cin>>a[i];
cnt[a[i]]++;
}
auto check=[&](int x)->bool{
ll fr=0,need=0;
for(int i=1;i<=n;i++){
if(x>=cnt[i]) //若当前工人可以在x时间内完成自己所精通的任务,则可以贡献出(x-cnt[i])/2的劳动力
fr+=(x-cnt[i])/2;
else // 若当前工人可以在x时间内不能完成自己所精通的任务,该任务还需的力量(cnt[i]-x)的劳动力
need+=(cnt[i]-x);
}
// 如果所贡献的劳动力大于所需要的劳动力,则在x时间内能完成所有任务
return need<=fr;
};
int l=1,r=N*2,mid;
while(l<r){
mid=l+r>>1;
if(check(mid)){
r=mid;
}
else{
l=mid+1;
}
}
cout<<l<<endl;
}
int main()
{
IOS
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}
/*
2 4
1 2 1 2
2 4
1 1 1 1
5 5
1 1 2 2 2
*/