每个输入包含一个测试用例。
每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。
接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。
接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。
保证不存在两项工作的报酬相同。
对于每个小伙伴,在单独的一行输出一个整数表示他能得到的最高报酬。如果他找不到工作,则输出0。一个工作可以被多个人选择。
3 3 1 100 10 1000 1000000000 1001 9 10 1000000000
100 1000 1001
按照工作难度对工作数组排序后,遍历有序数组,更新报酬为当前难度下的最大报酬。而后,对每个伙伴只需二分搜索确定其胜任的最大工作难度即可获取当下最大报酬。
public class FindJob { public static void main(String[] args) { Scanner in = new Scanner(System.in); int jobNum = in.nextInt(); int friendNum = in.nextInt(); int[][] jdArray = new int[jobNum][2]; for (int x = 0; x < jobNum; x++) { jdArray[x][0] = in.nextInt(); jdArray[x][1] = in.nextInt(); } int[] ability = new int[friendNum]; for (int x = 0; x < friendNum; x++) { ability[x] = in.nextInt(); } process2(jdArray, ability); } public static void process2(int[][] jdArray, int[] ability) { // 按照工作难度升序排序 Arrays.sort(jdArray, (int[] jd1, int[] jd2) -> {return jd1[0] - jd2[0];}); // 更新每个工作的报酬为当前难度所能获取的最大报酬 for (int i = 0; i < jdArray.length - 1; i++) { if (jdArray[i][1] > jdArray[i + 1][1]) { jdArray[i + 1][1] = jdArray[i][1]; } } // 二分查找确定能胜任的最大工作难度及其最大报酬 for (int i = 0; i < ability.length; i++) { int index = Arrays.binarySearch(jdArray, new int[] {ability[i], 0}, (int[] jd1, int[] jd2) ->{ return jd1[0] - jd2[0];}); index = index < 0 ? -(index + 1) - 1: index; System.out.println(index >= 0 ? jdArray[index][1] : 0); } } }
//非原创,借鉴楼上求天求地求offer解析,将TreeMap的使用改为二分查找 import java.util.*; public class Main{ static int n,m; public static void main(String[] args){ Scanner sc = new Scanner(System.in); n = sc.nextInt(); m = sc.nextInt(); int[][] t = new int[n][2]; for(int i=0;i<n;i++){ t[i][0] = sc.nextInt(); t[i][1] = sc.nextInt(); } //自定义排序 Arrays.sort(t,new Comparator<int[]>(){ @Override public int compare(int[] a,int[] b){ return a[0]-b[0]; } }); //dp使得对应的工作难度获得最大酬劳 for(int i=1;i<n;i++){ t[i][1] = max(t[i-1][1],t[i][1]); } for(int i=0;i<m;i++){ int a = sc.nextInt(); int index = find(a,t); if(index==-1) System.out.println(0); else System.out.println(t[index][1]); } } //二分查找 public static int find(int a,int[][] s){ int mid = (0+n)/2; int lo=0,hi=n-1; while(lo<=hi){ mid = (lo+hi)/2; if(a<s[mid][0]){ hi=mid-1; } else if(a>s[mid][0]){ lo=mid+1; } else if(a==s[mid][0]){ return mid; } } return hi; } public static int max(int a,int b){ if(a>b) return a; return b; } }
import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner s=new Scanner(System.in); int n=s.nextInt();//工作数量 int m=s.nextInt();//小伙伴的数量M int[][] work=new int[n][2]; for (int i = 0; i <n; i++) { for (int j=0;j<2;j++){ work[i][j]=s.nextInt(); } }//工作的难度Di和报酬Pi 放在二维数组里 //System.out.println(Arrays.deepToString(work)+"ce1");//日志检测 int[] fri=new int[m]; for (int i = 0; i < m; i++) { fri[i]=s.nextInt(); }//M个小伙伴的能力值Ai //System.out.println(Arrays.toString(fri)+"ce2");//日志检测 for (int i=0;i<fri.length;i++){ int temp=0;//保存可以接受的工作中 最大的报酬 for (int k=0;k<work.length;k++){ if (fri[i]>=work[k][0] && temp<work[k][1]){//如果能力值大于难度 temp=work[k][1]; } } System.out.println(temp); } } }
看注释。
import java.util.*; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int m = scanner.nextInt(); int[][] work = new int[n][2]; for(int i = 0; i< n; i++) { work[i][0] = scanner.nextInt(); work[i][1] = scanner.nextInt(); } Arrays.sort(work, new Comparator() { // 按照第一行排序 [@Override](/profile/992988) public int compare(int[] o1, int[] o2) { return o1[0] - o2[0]; } }); // dp 工资,使得对应工作能力对应最大工资 // map.put(work[0][0],work[0][1]); // 第一个放第一个,不变。 for(int i = 1; i< n; i++) { work[i][1] = Math.max(work[i-1][1],work[i][1]); } // 使用二分查找,小于等于工作难度的最大元素。 for(int i = 0; i< m; i++) { int skills = scanner.nextInt(); if(skills < work[0][0]) System.out.println(0); // 第一个都胜任不了。 else{ int index = binarySearchMax(work,skills); System.out.println(work[index][1]); } } } private static int binarySearchMax(int[][] work, int skills) { int low = 0; int high = work.length -1; while (low <= high) { int mid = low + (high -low) /2; if(work[mid][0] > skills) { high = mid -1; } else { if(mid == work.length-1 || work[mid+1][0] > skills) { return mid; } else { low = mid +1; } } } // 第一个元素都被它 大。 return -1; } }
#include<iostream> (720)#include<algorithm> #include<queue> (789)#include<vector> using namespace std; struct Work { int hard; int profit; }; struct Ai { int val; int seq; }; class Cmp1 { public: bool operator()(const Work& a, const Work& b) { return a.hard > b.hard; } }; class Cmp2 { public: bool operator()(const Work& a, const Work& b) { return a.profit < b.profit; } }; class Cmp3 { public: bool operator()(const Ai& a, const Ai& b) { return a.val < b.val; } }; class Cmp4 { public: bool operator()(const Ai& a, const Ai& b) { return a.seq < b.seq; } }; void Get_Max_award(vector<Work>& w, vector<Ai>& v) { priority_queue<Work, vector<Work>, Cmp1> hq(w.begin(),w.end()); priority_queue<Work, vector<Work>, Cmp2> pq; sort(v.begin(), v.end(),Cmp3()); for (size_t i = 0; i < v.size(); i++) { while (!hq.empty()&&v[i].val >= hq.top().hard) { pq.push(hq.top()); hq.pop(); } v[i].val = pq.top().profit; } sort(v.begin(), v.end(), Cmp4()); } int main() { int n, m; while (cin >> n >> m) { vector<Work> w(n); for (int i = 0; i < n; i++) { cin >> w[i].hard; cin >> w[i].profit; } vector<Ai> v(m); for (int i = 0; i < m; i++) { cin >> v[i].val; v[i].seq = i; } Get_Max_award(w, v); for (int i = 0; i < m; i++) cout << v[i].val << endl; } return 0; }求解我这个为啥只能过60%?
import java.util.Arrays; import java.util.Scanner; public class Main { private static int[][] Jobs; private static int N, M; public static void main(String[] args) { Scanner sc = new Scanner(System.in); N = sc.nextInt();//工作 M = sc.nextInt();//人 Jobs = new int[N][2]; for (int i = 0; i < N; ++i) { Jobs[i][0] = sc.nextInt(); Jobs[i][1] = sc.nextInt(); } Arrays.sort(Jobs, (int[] a, int[] b) -> { return a[0] - b[0]; }); for (int i = 1; i < N; i++) { Jobs[i][1] = Math.max(Jobs[i][1], Jobs[i - 1][1]); } for (int i = 0; i < M; i++) { int ai = sc.nextInt(); if (ai < Jobs[0][0]) { System.out.println(0); } else if (ai >= Jobs[N - 1][0]) { System.out.println(Jobs[N - 1][1]); } else { binarySearch(ai); } } } private static void binarySearch(int ai) { int lo = 0; int hi = N; //第一个大于 while (lo < hi) { int mid = lo + (hi - lo) / 2; if (Jobs[mid][0] < ai) { lo = mid + 1; } else if (Jobs[mid][0] > ai) { hi = mid; } else { System.out.println(Jobs[mid][1]); return; } } System.out.println(Jobs[hi - 1][1]);//最后一个不大于 } }
之前自己做的测试用例没有完全过,参考了其他小伙伴的思路。 |
public class Main{ private static int binarySearchMax(int[][] work, int skills) { int low = 0; int high = work.length - 1; while (low <= high) { int mid = low + (high - low) / 2; if (work[mid][0] > skills) { high = mid - 1; } else { if (mid == work.length - 1 || work[mid + 1][0] > skills) { return mid; } else { low = mid + 1; } } } // 第一个元素都被它 大。 return -1; } public static void main(String[] args) { Scanner s = new Scanner(System.in); int N = 0; int M = 0; N = s.nextInt(); //工作数量 M = s.nextInt(); //小伙伴的数量 int DIPI[][] = new int[N][2]; //二维数组来存储工作难度和报酬 for (int i = 0; i < N; i++) { DIPI[i][0] = s.nextInt();//工作难度 DIPI[i][1] = s.nextInt(); } //对工作难度进行排序 Arrays.sort(DIPI, new Comparator<int[]>() { // 按照第一行排序 [@Override] public int compare(int[] o1, int[] o2) { return o1[0] - o2[0]; } }); // 更新每个工作的报酬为当前难度所能获取的最大报酬 for (int i = 0; i < DIPI.length - 1; i++) { if (DIPI[i][1] > DIPI[i + 1][1]) { DIPI[i + 1][1] = DIPI[i][1]; } } //Ai 表示工作能力 int Ai[] =new int[M]; for (int j = 0; j < M; j++) { Ai[j] = s.nextInt(); int index = binarySearchMax(DIPI, Ai[j]); if(index==-1) System.out.println(0); else { System.out.println(DIPI[index][1]); } } } }
package com.jerehao.playground;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class No1 {
private static int n;
private static int m;
private static int[][] works;
private static int[][] workers;
public static void main(String[] args){
int loop = 1;
System.setIn(No1.class.getResourceAsStream("1.txt"));
Scanner scanner = new Scanner(System.in);
//loop = scanner.nextInt();
for (int i = 0; i < loop; ++i) {
n = scanner.nextInt();
m = scanner.nextInt();
works = new int[n][2]; // 0 难度,1 报酬
workers = new int[m][2]; // 0 难度,1 最大报酬
for (int j = 0; j < n; j++) {
works[j][0] = scanner.nextInt();
works[j][1] = scanner.nextInt();
}
for (int j = 0; j < m; j++) {
workers[j][0] = scanner.nextInt();
}
solve();
output();
}
scanner.close();
}
private static void solve() {
Arrays.sort(works, Comparator.comparingInt(a -> a[0]));
int max = works[0][1];
for (int i = 1; i < n; i++) {
if(works[i][1] < max)
works[i][1] = max;
else
max = works[i][1];
}
for (int i = 0; i < m; i++) {
int p = 0, q = n - 1;
while (p <= q) {
int mid = (p + q) / 2;
if(works[mid][0] < workers[i][0])
p = mid + 1;
else if(works[mid][0] > workers[i][0])
q = mid - 1;
else {
q = mid;
break;
}
}
workers[i][1] = q < 0 ? 0 :works[q][1];
}
}
private static void output() {
for (int i = 0; i < m; i++) {
System.out.println(workers[i][1]);
}
}
}
import java.util.*; public class Main { public static void main(String[] args) { // 每个输入包含一个测试用例。 HashMap, Integer> work = new HashMap, Integer>(); ArrayList Dis = new ArrayList(); ArrayList ableList = new ArrayList(); Scanner sc = new Scanner(System.in); // 每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N和小伙伴的数量M(M。 String num = sc.nextLine(); //工作的数量 if (num == null || num == "") { return; } String N = toArr(num)[0]; //小伙伴的数量 String M = toArr(num)[1]; // 接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di和报酬Pi(Pi。 for (Integer i = 0; i parseInt(N); i++) { String s = sc.nextLine(); if (num == null || num == "") { continue; } String[] work_info = toArr(s); if (work_info.length == 2) { work.put(Integer.parseInt(work_info[0]), Integer.parseInt(work_info[1])); } } // 接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai。 String s = sc.nextLine(); String[] able_info = toArr(s); for (int i = 0; i length; i++) { ableList.add(Integer.parseInt(able_info[i])); } // 对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。 for (int i = 0; i parseInt(M); i++) { Integer Ai = ableList.get(i); Set work_set = work.keySet(); Iterator iterator = work_set.iterator(); while (iterator.hasNext()) { Dis.add(iterator.next()); } Integer salaryMax = 0; for (int i1 = 0; i1 ; i1++) { if (Ai >= Dis.get(i1) && work.get(Dis.get(i1)) > salaryMax) { salaryMax = work.get(Dis.get(i1)); } } System.out.println(salaryMax); } // 保证不存在两项工作的报酬相同。 } public static String[] toArr(String str) { String[] split = str.trim().split(" "); return split; } }
整个题目结构非常简单,就是求 小于等于能力范围内的最高奖赏。
public class FindJob {
static class Job implements Comparable<Job> {
int di;
int pi;
public Job(int di, int pi){
this.di = di;
this.pi = pi;
}
@Override
public int compareTo(Job o) { //根据难度来排序
return this.di - o.di;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
Job[] jobs = new Job[N];
int[] ai = new int[M];
for(int i = 0; i < N; i++){
jobs[i] = new Job(scanner.nextInt(), scanner.nextInt());
}
for(int i = 0; i < M; i++){
ai[i] = scanner.nextInt();
}
Arrays.sort(jobs); //根据难度来排序
// 通过排序后,如果难度小的报酬大于难度大的报酬,那么
// 给难度大的重新赋值新的报酬,这是为了在查找下面更好计算
for(int i = 1; i < jobs.length; i++){
if(jobs[i].pi < jobs[i-1].pi)
jobs[i].pi = jobs[i-1].pi;
}
// 遍历每一个人,根据它的能力去找相应的报酬
for(int i = 0; i < M; i++){
// 通过二分查找得到小于等于能力的难度的工作
int x = findLastEqualSmaller(jobs, ai[i]);
/*
如果没有上面那个报酬替换的过程,就需要再进行遍历一次,这样ac不过
int max = 0;
for(int j = 0; j <= x; j++){
max = Math.max(max, jobs[j].pi);
}
*/
if(x == -1){
//当不存在的时候,说明没有工作合适,返回0
System.out.println(0);
}else{
System.out.println(jobs[x].pi);
}
}
}
// 小于等于key的索引,如果没有,那么返回-1
static int findLastEqualSmaller(Job[] array, int key) {
int left = 0;
int right = array.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid].di > key) {
right = mid - 1;
}else {
left = mid + 1;
}
}
return right;
}
}