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;
}
posted @ 2022-08-04 20:43  Vijurria  阅读(44)  评论(0编辑  收藏  举报