每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
3 3 1 100 10 1000 1000000000 1001 9 10 1000000000
100 1000 1001
都没Python AC代码 在这里添加一个 思想还是借鉴最高票 用maps[key]
表示能力值为key
所能取得的最高报酬 代码如下:
import sys def main(): lines = sys.stdin.readlines() lines = [l.strip().split() for l in lines if l.strip()] n, m = int(lines[0][0]), int(lines[0][1]) res = [0] * (n + m) abilities = list(map(int, lines[-1])) maps = dict() for index, l in enumerate(lines[1:-1]): d, s = int(l[0]), int(l[1]) maps[d] = s res[index] = d for index, ability in enumerate(abilities): res[index + n] = ability if ability not in maps: maps[ability] = 0 res.sort() maxSalary = 0 for index in range(n + m): maxSalary = max(maxSalary, maps[res[index]]) maps[res[index]] = maxSalary for index in range(m): print(maps[abilities[index]]) if __name__ == '__main__': main()
#include <iostream> #include <string> #include <vector> #include <algorithm> struct Work{ int d;//工作难度 int p;//工作报酬 }; struct Person{ int a;//能力值 int p;//报酬 int index;//表示小伙伴的序号 }; using namespace std; bool cmp1(Work a,Work b){ return a.d < b.d; } bool cmp2(Person a,Person b){ return a.a < b.a; } bool cmp3(Person a,Person b){ return a.index < b.index; }int main(){ int n;//工作的数量 int m;//小伙伴的数量 cin >> n >>m; Work* work = new Work[n]; for(int i = 0;i < n;i++){ cin >> work[i].d >> work[i].p; } Person* person = new Person[m]; for(int i = 0;i < m;i++){ cin >> person[i].a; person[i].index = i; } sort(work,work+n,cmp1); sort(person,person+m,cmp2); int j = 0; int max_money = 0; for(int i = 0;i < m;i++){ for(;j < n;j++){ if(person[i].a < work[j].d) break; max_money = max(max_money,work[j].p); } person[i].p = max_money; } sort(person,person+m,cmp3); for(int i = 0;i < m;i++){ cout << person[i].p << endl; } delete[] work; delete[] person; return 0; }
import sys
import bisect
task = {}
lines = sys.stdin.readlines()
n, m = map(int, lines[0].strip().split()) // 由于有空行,这句可以不写
for line in lines[1:-1]:
if not line.strip().split(): //存在空行,你能信...
continue
a, b = map(int, line.strip().split())
task[a] = max(task.get(a, 0), b)
arr = sorted(task.keys())
for i in range(1, len(arr)):
if task[arr[i]] < task[arr[i -1]]:
task[arr[i]] = task[arr[i -1]]
skills = map(int, lines[-1].strip().split())
for skill in skills:
if skill in task:
print(task[skill])
else:
ind = bisect.bisect(arr, skill)
if ind == 0:
print(0)
else:
print(task[arr[ind -1]])
本套8道题全部pass的C++代码已挂到了我的GitHub(https://github.com/shiqitao/NowCoder-Solutions)
牛客网上的其他题目解答也在持续更新。
#include <iostream> #include <algorithm> using namespace std; struct Work { int d, p; }; struct People{ int a, index, money; }; bool cmp1(Work a, Work b) { return a.d < b.d; } bool cmp2(People a, People b) { return a.a < b.a; } bool cmp3(People a, People b) { return a.index < b.index; } int main() { int n, m; cin >> n >> m; Work *work = new Work[n]; for (int i = 0; i < n; i++) { cin >> work[i].d >> work[i].p; } People *people = new People[m]; for (int i = 0; i < m; i++) { cin >> people[i].a; people[i].index = i; } sort(work, work + n, cmp1); sort(people, people + m, cmp2); int j = 0, maxMoney = 0; for (int i = 0; i < m; i++) { while (j < n) { if (work[j].d > people[i].a) { break; } maxMoney = max(maxMoney, work[j].p); j++; } people[i].money = maxMoney; } sort(people, people + m, cmp3); for (int i = 0; i < m; i++) { cout << people[i].money << endl; } delete[] work; delete[] people; return 0; }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner input=new Scanner(System.in); int n = input.nextInt(); int m = input.nextInt(); //存放能力值 int[] ability = new int[m]; //利用TreeMap,因为它里面的数据是默认按照key升序排列,方便比较 Map<Integer,Integer> map = new TreeMap<Integer,Integer>(); //存入难度和薪酬 for(int i = 0; i < n; i++){ int hard = input.nextInt(); int money = input.nextInt(); map.put(hard,money); } //存入小伙伴的能力 for(int i=0;i<m;i++){// int t = input.nextInt(); ability[i]=t; //不在工作难度边界处的,放入map,且对应薪酬为0 //若能力和工作难度相等,则不存,因为已经有了这组数据,下次比较的时候可以直接用 if(!map.containsKey(t)){ map.put(t,0); } } //Map.Entry用户遍历map的key和value值 int max = Integer.MIN_VALUE; for(Map.Entry<Integer,Integer> entry:map.entrySet()){ //map的值如下: // key value // 1 100 // 9 0 // 10 1000 // 10000000000 1001 max = Math.max(max, entry.getValue()); //更新之后: // key value // 1 100 // 9 100 // 10 1000 // 10000000000 1001 map.put(entry.getKey(), max);//更新不在工作难度边界处的薪酬 } for(int i = 0; i < m; i++){ System.out.println(map.get(ability[i])); } } }
import java.util.Scanner; import java.util.Arrays; import java.util.Comparator; class Work { int difficulty; int reward; public Work(int difficulty, int reward) { super(); this.difficulty = difficulty; this.reward = reward; } } public class Main { public static void main(String[] args) { findwork(); } public static void findwork() { Scanner in = new Scanner(System.in); int n = in.nextInt();// 工作数量 int m = in.nextInt();// 人数 Work[] works = new Work[n];// 存储n份工作 int[] dp = new int[n];// dp[n]:难度小于等于works[n].difficulty的工作的最高报酬 // 读入n份工作 for (int i = 0; i < n; i++) { int difficulty = in.nextInt(); int reward = in.nextInt(); Work work = new Work(difficulty, reward); works[i] = work; } // 根据工作的难度,对n份工作从小到大排序 Arrays.sort(works, new Comparator<Work>() { @Override public int compare(Work o1, Work o2) { return o1.difficulty - o2.difficulty; } }); // dp[i]:记录难度小于等于works[i].difficulty的最大报酬 dp[0] = works[0].reward; for (int i = 1; i < works.length; i++) { dp[i] = dp[i - 1] > works[i].reward ? dp[i - 1] : works[i].reward; } for (int i = 0; i < m; i++) { int capability = in.nextInt(); // 能力值小于所有的工作的难度 if (capability < works[0].difficulty) { System.out.println(0); continue; } // 能力值大于等于所有的工作的难度 if (capability >= works[n - 1].difficulty) { System.out.println(dp[n - 1]); continue; } // 二分查找,找到第一个小于capability的work int low = 0; int high = n - 1; while (low <= high) { int middle = (low + high) / 2; // works[middle]是符合能力值,且难度最大的工作 if (works[middle].difficulty <= capability && works[middle + 1].difficulty > capability) { System.out.println(dp[middle]); break; } // 找到难度等于能力值,且下标最大的工作 if (works[middle].difficulty == capability) { // 找到最后一个符合capability的工作 int index = middle; while (index + 1 < n && works[index + 1].difficulty == capability) { index++; } System.out.println(dp[middle]); break; } else if (capability > works[middle].difficulty) { low = middle + 1; } else if (capability < works[middle].difficulty) { high = middle - 1; } } } } }
// 懒得用Map,自己定义一个Node,存放工作的难度,工资,以及小于等于当前难度的所有工作中
// 最高的工资。用二分查找找到最接近且小于等于能力值的下标。
// 这个题输入有问题,所以BufferReader用不了会卡90%的数组越界,Scanner又非常慢
// 想要快速读入的同学可以使用StreamTokenizer
// 不过真实校招下,输入一般不会有问题;也基本不会因为Scanner超时
import java.util.*; import java.io.*;
public class Main{
static class Node{
int key;
int value;
int maxPay;
Node(int key, int value){
this.key = key;
this.maxPay = this.value = value;
}
}
public static void main(String[] args) throws IOException{
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
Node[] nodes = new Node[n];
for(int i = 0; i < n; i++){
nodes[i] = new Node(sc.nextInt(), sc.nextInt());
}
Arrays.sort(nodes, (Node n1, Node n2)->n1.key - n2.key);
for(int i = 1; i < n; i++){
if(nodes[i].maxPay < nodes[i-1].maxPay)
nodes[i].maxPay = nodes[i-1].maxPay;
}
StringBuilder sb = new StringBuilder();
for(int i = 0; i < m; i++){
int index = binarySearch(nodes, sc.nextInt());
if(index < 0) sb.append(0);
else sb.append(nodes[index].maxPay);
sb.append("\n");
}
System.out.print(sb.toString());
sc.close();
//br.close();
}
private static int binarySearch(Node[] nodes, int key){
int from = 0; int to = nodes.length-1;
int mid = 0;
while(from <= to){
mid = (from + to)>>1;
if(nodes[mid].key == key) return mid;
else if(nodes[mid].key < key) from = mid+1;
else to = mid -1;
}
return to; // to is floor and from is ceil
}
}
import java.util.Arrays; import java.util.Comparator; import java.util.Scanner; /** * @author qianyihui * @date 2019-07-30 * * 题目描述: * 为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。 * 在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。 * 牛牛的小伙伴太多了,于是他只好把这个任务交给了你。 * * 输入描述: * 每个输入包含一个测试用例。 * 每个测试用例的第一行包含两个正整数,分别表示工作的数量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 * * 时间复杂度是O(NlogN)。空间复杂度是O(N)。 * * 运行时间:2128ms。占用内存:78688k。 */ public class Main { private static class Work { int hard; int salary; Work(int hard, int salary) { this.hard = hard; this.salary = salary; } } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int N = scanner.nextInt(), M = scanner.nextInt(); Work[] works = new Work[N]; for (int i = 0; i < N; i++) { int num1 = scanner.nextInt(), num2 = scanner.nextInt(); works[i] = new Work(num1, num2); } //对Work按难度从易到难进行排序 Arrays.sort(works, Comparator.comparingInt(work -> work.hard)); //maxSalary[i]代表works数组[0, i]范围内的工资的最大值 int[] maxSalary = new int[N]; int max = Integer.MIN_VALUE; for (int i = 0; i < N; i++) { maxSalary[i] = Math.max(max, works[i].salary); max = maxSalary[i]; } for (int i = 0; i < M; i++) { int num = scanner.nextInt(); int index = ceil(works, num); //寻找难度上界,ceil函数二分查找 if (index == works.length) { //如果说个人能力num大于所有工作的难度值 System.out.println(maxSalary[N - 1]); //取工资最高的那个工作 } else if (works[index].hard > num) { //找到了难度上界,但是该上界值大于个人能力num if (index == 0) { //如果上界索引是0,这代表这个人不胜任任何工作 System.out.println("0"); //不胜任任何工作,其最高工资自然是0 } else { //否则,这个人能胜任[0, index - 1]范围内的工作 System.out.println(maxSalary[index - 1]); } } else if (works[index].hard == num) { //找到了难度上界,且该上界值等于个人能力num System.out.println(maxSalary[index]); } } } private static int ceil(Work[] works, int hard) { int left = 0, right = works.length; while (left < right) { int mid = left + ((right - left) >> 1); if (works[mid].hard <= hard) { left = mid + 1; } else { right = mid; } } if (left - 1 >= 0 && works[left - 1].hard == hard) { return left - 1; } return left; } }
#include<bits/stdc++.h> using namespace std; void solution(vector<pair<int,int> >& work,vector<pair<int,int> >& abilitys) { sort(work.begin(),work.end(),greater<pair<int,int>>()); sort(abilitys.begin(),abilitys.end(),greater<pair<int,int>>()); vector<pair<int,int> > ans; int i = 0,j = 0; while(j < abilitys.size()) { while(i < work.size() && work[i].second > abilitys[j].first) ++i; ans.push_back(pair<int,int>(abilitys[j].second,i != work.size() ? work[i].first : 0)); j++; } sort(ans.begin(),ans.end()); for(int i = 0; i < ans.size();++i) cout<<ans[i].second<<endl; } int main() { int N,M; while(cin>>N>>M) { vector<pair<int,int> > work; vector<pair<int,int> > abilitys; int hard,profit,abili; for(int i = 0;i < N;++i) { cin>>hard>>profit; work.push_back(pair<int,int>(profit,hard)); } for(int i = 0;i < M;++i) { cin>>abili; abilitys.push_back(pair<int,int>(abili,i)); } solution(work,abilitys); } return 0; }
#include<iostream> #include<queue> #include<algorithm> #include<unordered_map> using namespace std; using ll = long long; using PII = pair<ll, ll>; const ll N = 1e5 + 5; ll b[N]; ll c[N]; PII a[N]; int main() { int n, m; cin >> n >> m; for (int i = 0; i < n; ++i) { cin >> a[i].first >> a[i].second; } sort(a, a + n); for (int i = 0; i < m; ++i) { cin >> b[i]; c[i] = b[i]; } sort(b, b + m); unordered_map<ll, ll> ans; priority_queue<ll> q; for (int i = 0, j = 0; j < m; ++j) { while (i < n && a[i].first <= b[j]) { q.push(a[i].second); i++; } ans[b[j]] = q.empty() ? 0 : q.top(); } for (int i = 0; i < m; ++i) { cout << ans[c[i]] << endl; } return 0; }
#include <iostream> #include <map> using namespace std; int main(){ int n, m; cin >> n >> m; map<int, int> works; int friends, hard=0, pay=0, maxp=0; for(int i=0; i<n; ++i){ cin >> hard >> pay; if(works.find(hard)!=works.end() && works[hard]>=pay) continue; works[hard]=pay; } for(auto it=works.begin(); it!=works.end(); ++it){ if(maxp > it->second){ it->second=maxp; continue; } maxp=it->second; } for(int i=0; i<m; ++i){ cin >> friends; cout << (--works.upper_bound(friends))->second << endl; } return 0; }
/*保持jobs这个map中,不但难度递增,收益也是递增的;如果一个工作难度比上一个 工作高,那么就不要插入这个工作;如果插入,那么检查后面的工作是否有收益比这个工 作更低的,如果有就删除。这样的话最后查询就只需要直接找能满足能力条件的那个。删 除总量不会超过插入总量即O(n),故整个算法时间复杂度不会超过O(nlogn+n+mlogn) ,空间占用很小。*/ #include <iostream> #include <map> using namespace std; int main() { int N, M; cin >> N >> M; map<long, long> jobs; jobs.insert(make_pair(0, 0)); for (int i = 0; i < N; i++) { long Di, Pi; cin >> Di >> Pi; auto iter = jobs.lower_bound(Di); iter--; if (iter->second > Pi) continue; iter++; while (iter->second < Pi && iter != jobs.end()) iter = jobs.erase(iter); jobs.insert(make_pair(Di, Pi)); } for (int i = 0; i < M; i++) { long Ai; cin >> Ai; cout << (--jobs.upper_bound(Ai))->second << endl; } return 0; }
#include <bits/stdc++.h> using namespace std; struct Job{ int hard; int money; Job(int h, int m){ hard = h; money = m; } bool operator<(const Job& t)const{ return hard != t.hard ? (hard < t.hard) : (money > t.money); } }; int main(){ int n, m; scanf("%d%d", &n,&m); vector<Job> job(n, Job(0, 0)); for(int i=0; i<n; i++){ int ha, mo; scanf("%d%d", &ha,&mo); job[i].hard = ha; job[i].money = mo; } sort(job.begin(), job.end()); map<int, int> rmap; rmap[job[0].hard] = job[0].money; Job pre = job[0]; for(int i=1; i<n; i++){ if(job[i].hard != pre.hard && job[i].money > pre.money){ rmap[job[i].hard] = job[i].money; pre = job[i]; } } for(int i=0; i<m; i++){ int key; scanf("%d", &key); auto tmp = rmap.lower_bound(key); if(rmap.count(key) == 0) --tmp; cout << tmp->second << endl; } return 0; }
#include <bits/stdc++.h> using namespace std; struct W{ int d, p; }; struct P{ int a, idx, s; }; bool cmp1(W w1, W w2){ return w1.d < w2.d; } bool cmp2(P p1, P p2){ return p1.a < p2.a; } bool cmp3(P p1, P p2){ return p1.idx < p2.idx; } int main(){ int n, m; cin>>n>>m; W w[n]; P p[m]; for(int i=0;i<n;i++) cin>>w[i].d>>w[i].p; for(int i=0;i<m;i++){ cin>>p[i].a; p[i].idx = i; } sort(w, w+n, cmp1); sort(p, p+m, cmp2); int j=0; for(int i=0, t=0;i<m;i++){ for(;j<n;j++){ if(p[i].a < w[j].d) break; t = max(t, w[j].p); } p[i].s = t; } sort(p, p+m, cmp3); for(int i=0;i<m;i++) cout<<p[i].s<<endl; return 0; }
import bisect n_job,m = list(map(int,input().strip().split())) diff_to_wage = {} i = 0 while i < n_job: *** = list(map(int,input().strip().split())) if ***: diff,wage = *** diff_to_wage[diff] = max(diff_to_wage.get(diff,0),wage) i+=1 powers = [] while not powers: powers = list(map(int,input().strip().split())) #*** again!! keys = sorted(diff_to_wage.keys()) for i in range(1,len(keys)): if diff_to_wage[keys[i]] < diff_to_wage[keys[i-1]]: diff_to_wage[keys[i]] = diff_to_wage[keys[i-1]] for power in powers: if power in diff_to_wage: #in key time out 40% print(diff_to_wage[power]) else: ind = bisect.bisect(keys,power) if not ind: print(0) else: print(diff_to_wage[keys[ind-1]])
#include <iostream> #include <cstdio> #include <algorithm> #include <map> using namespace std; struct node{ int index=0; //表示第几个朋友 long D;//表示能力 long P=0;//表示报酬 }; node works[200004]; long a[100004]; bool temf(node n1,node n2){ return n1.D<n2.D; } int main(){ int n,m; while(cin>>n>>m){ int i; for(i=0;i<n;i++){ cin>>works[i].D>>works[i].P; //各种工作信息录入,index默认为0 } for(int j=0;j<m;j++){ cin>>works[i+j].D; //所有朋友信息录入,报酬默认为0 ,同时录入第几个朋友 works[i+j].index=j; } sort(works,works+m+n,temf);//整体排序 int tem=0; //存放当前能力下能得到的最大报酬 for(int t=0;t<m+n;t++){ if(works[t].P >tem){ tem=works[t].P; } if(works[t].P == 0){ a[works[t].index]=tem;//根据朋友index填入最终的输出数组。 } } for(int r=0;r<m;r++){ printf("%d\n",a[r]);//顺序输出 } } return 0; }