方法:
排序+双指针
想法:
工人们只能做难度小于等于他能力值的工作,将工作的难度按升序排序,遍历工作难度的同时记录最大收益,一定是当前工人能获得的最大收益。
算法:
由于不止一个工人,如果每个工人都按上述操作进行,时间复杂度是O(n*m)的,不能通过此题。考虑将工人的能力值也按升序排序,不失一般性,worker[i]能做的工作,worker[i+1]也一定能做。
顺序遍历工人的同时,需要一个指针index指向最后一个难度<=当前工人能力值的工作、一个变量max_记录最大利润,随着遍历的进行拓展新的工作,更新max_;
排序使用的方式有很多种,可以使用map自动排序,将difficulty和profit放入结构体中统一排序等,这里使用下标排序。
复杂度分析:
时间复杂度:O(NlogN+MlogM),其中 N 是工作个数,M 是工人数量,两次排序。
空间复杂度:O(max(N,M)),job_idx,worker_idx 的额外空间。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, m, index = 0, max_ = 0;
scanf("%d %d", &n, &m);
vector<int>difficulty(n), profit(n), worker(m);
for (int i = 0; i < n; i++)
scanf("%d %d", &difficulty[i], &profit[i]);
for (int i = 0; i < m; i++)
scanf("%d", &worker[i]);
vector<int>job_idx(n), worker_idx(m), ret(m);
iota(job_idx.begin(), job_idx.end(), 0);
sort(job_idx.begin(), job_idx.end(), [&](int& a, int& b) {return difficulty[a] < difficulty[b]; });
iota(worker_idx.begin(), worker_idx.end(), 0);
sort(worker_idx.begin(), worker_idx.end(), [&](int& a, int& b) {return worker[a] < worker[b]; });
for (int i = 0; i < m; i++)
{
while (index < job_idx.size() && difficulty[job_idx[index]] <= worker[worker_idx[i]])
max_ = max(max_, profit[job_idx[index++]]);
ret[worker_idx[i]] = max_;
}
for (int i = 0; i < m; i++)
printf("%d\n", ret[i]);
return 0;
}


京公网安备 11010502036488号