题目描述
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述:
每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
输出描述:
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
示例1
输入
3 3
1 100
10 1000
1000000000 1001
9 10 1000000000
输出
100
1000
1001
思想
实际上是贪心算法,在能力范围内,拿到最多的工资。
方法一:先根据工作的难易,对工作进行排序,由于题目已说,每个工作的薪资是不一样的,那么,对已经排好序的工作,对工作难易进行二分查找。如果工作i的难度大薪资低于工作i+1的难度小的薪资,在进行查询的时候,我们希望在二分查找的时候,输出的薪资是最高的,那么这种情况下的薪资是不要的,那么就可以让工作i的难度大薪资等于工作i+1的难度小的薪资,这样处理的结果就是:
(1,10) | (10,1000) | (20,90) | (100000000,1001) |
(1,10) | (10,1000) | (20,1000) | (100000000,1001) |
第一行的数据是根据工作难易进行排序后的,第二行数据,如果工作i的难度大薪资低于工作i+1的难度小的薪资,那么就可以让工作i的难度大薪资等于工作i+1的难度小的薪资。当工作难易度大时,比如查找20时,通过二分查找,能够输出正确的期望的最大的薪资。
主要操作:
- 根据工作难易程度进行排序
- 对工作难薪资的工作,让其薪资为排在前面的工作的薪资
- 二分查找
代码:
#include<iostream>
#include <algorithm>
using namespace std;
struct salary {
long int energy;
long int pay;
}job[100000];
int findSalary(salary a[], int left, int right, int k)
{
int i, j, t;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if (a[mid].energy < k) left = mid + 1;
else if (a[mid].energy >k) right = mid - 1;
else return mid;
}
return right;
}
bool cmp(salary a,salary b){
if(a.energy<b.energy) return true;//按困难值从小到大排序
else if(a.energy==b.energy &&a.pay>=b.pay) return true;
return false;
}
int main() {
int n, m, j, i, k;
long int mySalary;
while( cin >> n >> m){
for (i = 0; i < n; i++)
{
cin >> job[i].energy >> job[i].pay;
}
//1.排序
sort(job,job+n,cmp);//按困难值从小到大排序,复杂度NlogN
//2.重设复杂度高但是薪资低的工作的薪资,便于二分查找得出正确的答案
for (i = 1; i < n; i++)
if (job[i].pay < job[i - 1].pay)
job[i].pay = job[i - 1].pay;
for (i = 0; i < m; i++)
{
cin >> k;
//3.二分查找
mySalary = findSalary(job,0,n-1,k);
cout << job[mySalary].pay << endl;
}
}
return 0;
}
在进行排序的时候,最开始写的是快排,但是提交超时,通过80%,然后调用了库函数中的排序方法。
方法二:
这个方法使用map,非常方便和简单啊,当然是答题的大神做出来的。
#include<iostream>
#include<map>
using namespace std;
int main() {
map<int, int>Map;
int n, m;
cin >> n >> m;
int i;
int energy, pay;
for (i = 0; i < n; i++)
{
cin >> energy >> pay;
Map[energy] = pay;
}
int job[100000] ;
for (i = 0; i < m; i++)
{
cin >> job[i];
Map.insert(make_pair(job[i], 0));
}
int temp = 0;
for (map<int, int>::iterator it = Map.begin(); it != Map.end(); it++)
{
if (it->second < temp) it->second = temp;
else if (it->second > temp) temp = it->second;
}
for (i = 0; i < m; i++)
cout << Map[job[i]] << endl;
return 0;
}
当我尝试把单独输出每个工作的最大薪资时,像下面这样,就超时了……
for (i = 0; i < m; i++)
{
cin >> job[i];
Map.insert(make_pair(job[i], 0));
int temp = 0;
for (map<int, int>::iterator it = Map.begin(); it != Map.end(); it++)
{
if (it->second < temp) it->second = temp;
else if (it->second > temp) temp = it->second;
}
//for (i = 0; i < m; i++)
cout << Map[job[i]] << endl;
}