牛客网--牛牛找工作

题目描述

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

输入描述:

每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量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

一开始看到这个题的思路是按照工作酬金给工作排序,之后通过循环,寻找每个人能力范围之内酬金最高的工作,后来发现这样时间复杂度太高,通过率是80%

优化思路是:不仅给各项工作按酬金排序,同时按照每个人的能力给小伙伴排序,如果这项工作连能力高的小伙伴都无法胜任,那能力低的小伙伴又怎么会被聘用呢?因此之前能力高的小伙伴无法胜任的工作,排在后面的小伙伴自然不用再看。

将每个人小伙伴可以得到的酬金分配给他们之后,再恢复小伙伴一开始的次序就好(即输入时的次序)

代码:

#include<stdio.h>
#include<iostream>
#include <algorithm>
using namespace std;
typedef struct Stu1
{
    int a;  //a表示该项工作的难度
    int b;  //b表示该项工作的酬金
}Stu;
typedef struct Person1
{
    int No;       //No是为了记录小伙伴一开始的次序,便于之后恢复次序
    int Ability;  //Ability表示小伙伴的能力
}Person;
bool cmp1(Stu x,Stu y)
{
    return x.b > y.b;
}
bool cmp2(Person x,Person y)
{
    return x.Ability > y.Ability;
}
bool cmp3(Person x,Person y)
{
    return x.No < y.No;
}
int main()
{
    int N,M,i,j;
    int flag;
    scanf("%d%d",&N,&M);
    Stu stu[N],t;
    Person person[M];  //小伙伴
    for(i=0;i<N;i++)
    {
        scanf("%d%d",&stu[i].a,&stu[i].b);
    }
    for(i=0;i<M;i++)
    {
        scanf("%d",&person[i].Ability);
        person[i].No=i;
    }
    sort(stu,stu+N,cmp1);
    sort(person,person+M,cmp2);
    j=0;
    for(i=0;i<M;i++)
    {
        flag =0;
        for(;j<N;)     // j++未放在这里,就是为了优化程序,让一些没必要的工作不再循环,降低时间复杂度
        {
            if(stu[j].a<=person[i].Ability)
            {
                flag=1;
                person[i].Ability=stu[j].b;
                break;
            }
            j++;
        }
        if(flag==0)
        {
            person[i].Ability=0;
        }
    }
    sort(person,person+M,cmp3);   //恢复小伙伴之前的次序
    for(i=0;i<M;i++)
    {
        printf("%d\n",person[i].Ability);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值