本题借鉴学姐思路解题非本人。
题意:工人(n个),任务(m个),每个任务显示能够熟练完成该任务工人的编号,若工人能熟练完成该工作则1小时完成,不熟练则需要2小时;求完成所有任务所需最小时间?
题解:假设每个任务都先归能熟练完成该任务的相应工人完成,要使完成时间最小,需要将承担任务多的分配给给任务少的(分配方任务时长-1,被分配方任务时长+2),具体操作如下:
①用multiset维持存在重复元素并且有序(升序)的序列。
②统计每个工人熟练的任务数,并插入到集合中。
③判断最多任务数是否能分配给最小任务数(first - 1 >= last + 2)。
▪若可以,修改任务数(multiset元素的值不能在容器中进行修改,但可以插入和删除),继续判断;
▪若不可以,则表明当把当前最多任务数分配给最小任务数时,超过了当前最多任务数,所以当前最多任务数即为完成所有任务所需最小时间。
#include <bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define endl '\n'
#define N 200005
using namespace std;
const ll inf=0x3f3f3f3f;
const double PI=acos(-1);
const ll mod=1e9+7;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
multiset<int>v;
void solve()
{
v.clear();
int n,m,k;
cin >>n>>m;
int a[n+1]={0};
while(m--)
{
cin >>k;
a[k]++;
}
for(int i=1;i<=n;i++) v.insert(a[i]);
/* for(auto it:v)
{
cout <<it<<"fa"<<endl;
}*/
auto l=v.begin(),r=--v.end();
int ma=*r,mi=*l;
while(ma-1>=mi+2)
{
// cout <<"fag"<<endl;
v.erase(v.begin());
v.erase(--v.end());
v.insert(ma-1);
v.insert(mi+2);
l=v.begin();r=--v.end();
ma=*r,mi=*l;
}
cout <<ma<<endl;
}
int main()
{ios
int t;
cin >>t;
while(t--)
{
solve();
}
return 0;
}