2019网易笔试——牛牛找工作

题目描述

为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。

输入描述:

每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量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时,通过二分查找,能够输出正确的期望的最大的薪资。

主要操作:

  1. 根据工作难易程度进行排序
  2. 对工作难薪资的工作,让其薪资为排在前面的工作的薪资
  3. 二分查找

代码:

#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;
	}
		

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值