题目大意

  • 有 n 种药品,每种药品有两个属性:疼痛值 a_i功效值 b_i
  • 有 q 次查询,每次给定一个忍耐度 x
  • 要求:在所有 疼痛值 ≤ x 的药品中,找出 功效值最大 的那个
  • 若不存在满足条件的药品,输出 -1

解题思路

步骤 1:去重 & 保留最优

  • 对于相同的疼痛值 a,只保留功效值最大的那个(因为更优)
  • 可用 Map<Integer, Integer> 实现:map.put(a, max(map.get(a), b))

步骤 2:按疼痛值排序

  • 将所有不同的 a 值提取出来并升序排列(TreeSet

步骤 3:预处理前缀最大功效值

  • 因为疼痛值已排序,我们可以计算 前缀最大功效值即:对于每个疼痛值 a[i],记录所有 ≤ a[i] 的药品中的最大功效值
  • 这样,任意 x 查询时,只需找到 最大的 a[i] ≤ x,其对应的前缀最大值即为答案

步骤 4:二分查找

  • 在有序的疼痛值数组中,使用 二分查找 找到最后一个 ≤ x 的位置
  • 时间复杂度:O(log n) 每次查询

代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

public class Main {

	private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
	private static StreamTokenizer st = new StreamTokenizer(reader);
	private static PrintWriter writer = new PrintWriter(new OutputStreamWriter(System.out));

	private static int n, q;

	private static Map<Integer, Integer> map = new HashMap<>();
	private static TreeSet<Integer> set = new TreeSet<>();
	private static List<Integer> list;

	public static void main(String[] args) throws IOException {
		while (st.nextToken() != StreamTokenizer.TT_EOF) {
			n = (int) st.nval;

			for (int i = 0; i < n; i++) {
				st.nextToken();
				int a = (int) st.nval;
				st.nextToken();
				int b = (int) st.nval;
				set.add(a);
				map.put(a, Math.max(map.getOrDefault(a, 0), b));
			}
			list = new ArrayList<>(set);
			int tempMax = 0;
			for (Integer key : list) {
				tempMax = Math.max(tempMax, map.get(key));
				map.put(key, tempMax);
			}

			st.nextToken();
			q = (int) st.nval;

			while (q-- > 0) {
				st.nextToken();
				int x = (int) st.nval;
				int l = 0;
				int r = list.size() - 1;
				int ans = -1;
				while (l <= r) {
					int mid = (r - l) / 2 + l;
					if (list.get(mid) <= x) {
						ans = map.get(list.get(mid));
						l = mid + 1;
					} else {
						r = mid - 1;
					}
				}
				writer.println(ans);
			}

		}
		writer.flush();
		writer.close();
		reader.close();
	}

}