方法:
  排序+双指针

想法:
  工人们只能做难度小于等于他能力值的工作,将工作的难度按升序排序,遍历工作难度的同时记录最大收益,一定是当前工人能获得的最大收益。

算法:
  由于不止一个工人,如果每个工人都按上述操作进行,时间复杂度是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;
}