LC826. 安排工作以达到最大收益

原题链接
image.png

思路

  • 将工作按照难度进行排序。难度越大不一定收益就越多,但是可以在预处理(左边最大值辅助数组)之后,在O(1)时间内得知,满足条件的区间里面最大的收益值是多少。
  • 所谓预处理,就是建立一个left_max数组,该数组记录了出现在左边的最大值,left_max[i]表示从第0个位置,到第i个位置,出现的最大的数值。
  • 对于工人i而言,可以通过二分查找,在LC826.安排工作以达到最大收益 - 图2时间内找到difficulty值不大于worker[i]的区间的右端点,该端点记为x,那么这个工人能取得的最大收益就是left_max[x]

  • left_max数组预处理,left_max[i]表示从0i的最大数字 ```cpp vector left_max(n, 0); left_max[0] = pp[0].second;

for (int i = 1; i < n; i++) { left_max[i] = max(left_max[i - 1], pp[i].second); }

  1. - 二分查找,找左侧区间的右端点
  2. ```cpp
  3. while (left < right) {
  4. int mid = (left + right + 1) / 2;
  5. if (pp[mid].first <= num) {
  6. left = mid;
  7. } else {
  8. right = mid - 1;
  9. }
  10. }

代码

  1. class Solution {
  2. public:
  3. int findEnd(int num, vector<pair<int,int>>& pp) {
  4. int n = pp.size();
  5. int left = 0, right = n - 1;
  6. while (left < right) {
  7. int mid = (left + right + 1) / 2;
  8. if (pp[mid].first <= num) {
  9. left = mid;
  10. } else {
  11. right = mid - 1;
  12. }
  13. }
  14. if (pp[right].first <= num) {
  15. return right;
  16. } else {
  17. return -1;
  18. }
  19. }
  20. static bool cmp(const pair<int, int> p1, const pair<int, int> p2) {
  21. return p1.first < p2.first;
  22. }
  23. int maxProfitAssignment(vector<int>& difficulty, vector<int>& profit, vector<int>& worker) {
  24. int n = difficulty.size();
  25. vector<pair<int, int>> pp(n, {0, 0});
  26. for (int i = 0; i < n; i++) {
  27. pp[i].first = difficulty[i];
  28. pp[i].second = profit[i];
  29. }
  30. sort(pp.begin(), pp.end(), cmp);
  31. // 对于每个满足条件的条件,计算左边开始的最大收益值
  32. vector<int> left_max(n, 0);
  33. left_max[0] = pp[0].second;
  34. for (int i = 1; i < n; i++) {
  35. left_max[i] = max(left_max[i - 1], pp[i].second);
  36. }
  37. int cnt = 0;
  38. // 找到满足工人能力条件的区间的右端点,然后计算这个区间曾经出现过的最大值即可
  39. int worker_num = worker.size();
  40. for (int i = 0; i < worker_num; i++) {
  41. int right_end = findEnd(worker[i], pp);
  42. if (right_end == -1) {
  43. continue;
  44. } else {
  45. cnt += left_max[right_end];
  46. }
  47. }
  48. return cnt;
  49. }
  50. };