Educational Codeforces Round 131 (Rated for Div. 2) C. Schedule Management(二分)
https://codeforces.com/contest/1701/problem/C
有n个工人和m个任务。工人从1到n编号。每个任务I都有一个值ai——熟练完成该任务的工人的指数。
每个任务都应该分配一个工作人员。如果工人精通这项工作,他们在1小时内就能完成。否则,他们要花两个小时。
工人们平行工作,彼此独立。每个工人一次只能处理一项任务。
以尽可能早地完成任务的方式给工人分配所有任务。工作在时间0开始。完成所有任务的最短时间是多少?
投入
第一行包含一个整数t (1≤t≤104) —测试用例的数量。
每个测试用例的第一行包含两个整数n和m(1≤n≤m≤2⋅105)——工人的数量和任务的数量。
第二行包含m个整数a1,a2,…,am(1≤ai≤n)——第I个任务熟练的工人的指数。
所有测试用例的m之和不超过2⋅105.
输出
对于每个测试用例,打印一个整数——所有任务可以完成的最小时间。
input
4
2 4
1 2 1 2
2 4
1 1 1 1
5 5
5 1 3 2 4
1 1
1
output
2
3
1
1
很典型的二分寻找答案板子题
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cstdio>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<deque>
using namespace std;
const int N=200200;
const int M=1002;
typedef long long LL;
const LL mod=998244353;
LL a[N],b[N],n,m;
int sum[N];
map<LL,LL>mp;
bool check(LL x)
{
LL sum=0,cnt=0;
for(int i=1;i<=n;i++)
{
LL xx=mp[i];//这个人需要完成的工作量
//cout<<"x xx"<<x<<" "<<xx<<endl;
if(x>=xx) sum+=(x-xx)/2;//如果这个时间内这个人能干完所有活儿,sum就把多余的可以干活的次数装起来
else cnt+=(xx-x);//如果在这个时间之内这个人不能干完所有的活儿,那么就把需要别人帮忙干的次数装起来
}
//cout<<"sum cnt"<<sum<<" "<<cnt<<endl;
return sum>=cnt;//如果可以帮忙干的东西会多余需要帮忙干的(人比事儿多,那么就可行)
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
mp.clear();
cin>>n>>m;
for(int i=1;i<=m;i++)
{
LL xx;
cin>>xx;
mp[xx]++;//记录第几个人需要干多少次活儿xx属于1~n
}
//for(int i=1;i<=n;i++) cout<<mp[i]<<" "; cout<<endl;
//记录每个精通的人被用次数小于mid就可以继续用,
//不然就记录要用2个小时的工作+1,然后检查每个人能用于2个小时的工作的次数
LL l=1,r=2*m,ans;
while(l<r)
{
int mid=(l+r)/2;
//cout<<"mid"<<mid<<endl;
if(check(mid))
{
ans=mid;
r=mid;
}
else l=mid+1;
//cout<<"l r"<<l<<" "<<r<<endl;
}
//ans代表的是完成工作的时间
cout<<ans<<endl;
}
return 0;
}