登录
OAmaster

A robotic chemical delivery system for a college chemistry laboratory has been configured to work using only one type of glass flask per day. For each chemical ordered, it will be filled to a mark that is at least equal to the volume ordered. There are multiple flasks available, each with markings at various levels. Given a list of order requirements and a list of flasks with their measurements, determine the single type of flask that will result in minimal waste. Waste is the sum of marking - requirement for each order. Return the zero-based index of the flask type chosen. If there are multiple answers, return the minimum index. If no flask will satisfy the constraints, return -1. NOTE: The markings 2D array will be given in order of the flasks, i.e., the markings for the 0-index flask will be followed by markings of 1-index flask and so on. For each flask, the given markings will also be sorted in ascending order.

Constraints

An unknown secret for now

Example 1

Input:

requirements = [4, 6, 6, 7]
markings = [[0, 3], [0, 5], [0, 7], [1, 6], [1, 8], [1, 9], [2, 3], [2, 5], [2, 6]]

Output:

0

Explanation: The markings array is a 2D array where the first element is the flask number and the second an available marking. In this case, the first type has markings at 3, 5 and 7. The second type has them at 6, 8 and 9, and the third type has markings at 3, 5 and 6. Using the first flask type, the losses are 5-4=1, 7-6=1,7-6=1,7-7=0. 1+1+1+0=3 units wasted. Using the second flask type, losses are: 6-4 = 2, 6 - 6=0, 6-6=0, 8-7=1. 2+0 + 0 + 1 = 3 units wasted. The third flask type cannot be used because its maximum capacity is 6 and there is an order for 7. Two types of flasks can be used and 3 units will be lost. The lower index flask is at index 0.

解法

先按瓶子编号分组它们的刻度(已升序)。对每个瓶子用 bisect_left 二分找每个需求量对应的最小刻度,累计浪费值;若某个需求超过该瓶子最大刻度,跳过该瓶子。最后选浪费值最小且编号最小的瓶子。时间复杂度 O((M + F) log K),M 是需求数,F 是总刻度数,K 是单瓶刻度数。

from typing import List
from bisect import bisect_left

def chooseFlask(requirements: List[int], markings: List[List[int]]) -> int:
    flasks = {}
    for f, m in markings:
        flasks.setdefault(f, []).append(m)
    best_idx, best_waste = -1, float('inf')
    for idx in sorted(flasks.keys()):
        marks = flasks[idx]
        waste = 0
        ok = True
        for r in requirements:
            i = bisect_left(marks, r)
            if i == len(marks):
                ok = False
                break
            waste += marks[i] - r
        if ok and waste < best_waste:
            best_waste = waste
            best_idx = idx
    return best_idx
class Solution {
    int chooseFlask(int[] requirements, int[][] markings) {
        TreeMap<Integer, List<Integer>> flasks = new TreeMap<>();
        for (int[] m : markings) flasks.computeIfAbsent(m[0], k -> new ArrayList<>()).add(m[1]);
        int bestIdx = -1;
        long bestWaste = Long.MAX_VALUE;
        for (Map.Entry<Integer, List<Integer>> e : flasks.entrySet()) {
            List<Integer> marks = e.getValue();
            long waste = 0;
            boolean ok = true;
            for (int r : requirements) {
                int lo = 0, hi = marks.size();
                while (lo < hi) {
                    int mid = (lo + hi) >>> 1;
                    if (marks.get(mid) < r) lo = mid + 1; else hi = mid;
                }
                if (lo == marks.size()) { ok = false; break; }
                waste += marks.get(lo) - r;
            }
            if (ok && waste < bestWaste) { bestWaste = waste; bestIdx = e.getKey(); }
        }
        return bestIdx;
    }
}
class Solution {
public:
    int chooseFlask(vector<int>& requirements, vector<vector<int>>& markings) {
        map<int, vector<int>> flasks;
        for (auto& m : markings) flasks[m[0]].push_back(m[1]);
        int bestIdx = -1;
        long long bestWaste = LLONG_MAX;
        for (auto& [idx, marks] : flasks) {
            long long waste = 0;
            bool ok = true;
            for (int r : requirements) {
                auto it = lower_bound(marks.begin(), marks.end(), r);
                if (it == marks.end()) { ok = false; break; }
                waste += *it - r;
            }
            if (ok && waste < bestWaste) { bestWaste = waste; bestIdx = idx; }
        }
        return bestIdx;
    }
};