2071. 你可以安排的最多任务数目
思路
1.没有药丸:怎么匹配工人和任务,使得完成的任务数量尽可能多?
答:sort任务,sort工人,让力量值较小的工人完成消耗较少的任务
2.引入药丸:假设当前要完成k个任务(明确固定k),怎么挑选工人和任务,成功率更大?
答:挑选能力最强的k个工人,消耗最少的k个任务
3.二分答案
(1)单调性:假设当前要求完成的任务数1,2,...,k,...,逐渐增多,成功率怎么变化?
答:要求的任务数↑,成功率↓
(2)找到尽可能大的任务数:最优解
(3)外层:枚举任务数k,内层:要求完成k个任务时,怎么匹配工人
4.匹配工人
当前拿到了最强k个工人\([w_0,w_1,...,w_{k-1}]\),最容易k个任务\([t_0,t_1,...,t_{k-1}]\)
(1)错误思路:最强工人匹配最难任务,完成不了直接吃药
反例:tasks=[5,9,8,5,9],workers=[1,6,4,2,6],pills=1,strength=5
排序:tasks=[5,5,8,9,9],workers=[1,2,4,6,6]
挑选:[5,5,8],[4,6,6]
任务8怎么完成?如果让工人6吃药完成任务8,浪费了吗?
如果要服药,为什么不让力量值更小的工人4服药完成任务8,
留下较强的工人6,也许他不用服药也可以完成其他任务?
矛盾:把药丸给了最强的人,但是最强的人即使不吃药,也能做很多其他的任务,药丸应该给其他够得着的较弱的人,把强者省下来
(2)正确思路:
对于当前最难任务t,先找\(w>=t\)的首位工人,如果有,匹配;
如果没有,找\(w>=t-strength\)的首位工人,如果有,吃药匹配;
如果仍然没有,任务数为k时无法完成
解题过程
二分答案(最大化,向右找)+multiset
复杂度
- 时间复杂度:\(O(n(log(n))^2)\)
- 空间复杂度:\(O(n)\)
说明

代码
class Solution {
public:
int maxTaskAssign(vector<int>& tasks, vector<int>& workers, int pills, int strength) {
using ll=long long;
sort(tasks.begin(),tasks.end());
sort(workers.begin(),workers.end());
int n=tasks.size(),m=workers.size();
int lft=0,rgt=min(n,m),mid=0;
int remain=0;
bool flag=true;
while(lft<rgt){
mid=(lft+rgt+1)/2;
remain=pills;
flag=true;
multiset<int> mset;
for(int i=m-mid;i<=m-1;++i){
mset.insert(workers[i]);
}
for(int j=mid-1;j>=0;--j){
auto it=mset.lower_bound(tasks[j]);
if(it!=mset.end()){
mset.erase(it);
}
else{
auto it2=mset.lower_bound(tasks[j]-strength);
if(remain>0&&it2!=mset.end()){
mset.erase(it2);
remain--;
}
else{
flag=false;
break;
}
}
}
if(flag) lft=mid;
else rgt=mid-1;
}
return rgt;
}
};

浙公网安备 33010602011771号