// O(N log(N) + M * Q) where Q is the number of points on the convex hull of the // dishes. In the worst case, Q = N, leading to total complexity of O(NM). This // should exceed the time limit. However, if test cases were not well written // and did not hit the special case where Q=N, e.g. random-looking, then // Q=O(log(N)), and this would pass. #include #include #include #include #include #include using namespace std; using Point = array; // Cross product, the signed area of these three points. int64_t area(Point O, Point P, Point Q) { return (P[0] - O[0]) * (Q[1] - O[1]) - (P[1] - O[1]) * (Q[0] - O[0]); } struct Dish { Point p = {}; int index = -1; bool operator<(const Dish &other) const { Point pp = {p[0], -p[1]}; Point other_pp = {other.p[0], -other.p[1]}; // TODO: remove index? return pp < other_pp || (pp == other_pp && index < other.index); } }; struct Person { Point p = {}; int index = -1; }; template vector read_input(int N) { vector read(N); for (int i = 0; i < N; i++) { read[i].index = i; for (int k = 0; k < 2; ++k) { cin >> read[i].p[k]; assert(read[i].p[k] >= 0); // Prevent overflows. assert(read[i].p[k] <= 1e8); } } return read; } // Adds a new point to 'hull', maintaining the property that 'hull' is // an upper convex hull of all added points. void extend_hull(const Dish &new_point, std::vector &hull) { while (hull.size() >= 2 && // >0 instead of >= to keep aligned points. area(hull[hull.size() - 2].p, hull.back().p, new_point.p) > 0) { hull.pop_back(); } hull.push_back(new_point); } // Computes the upper convex hull of 'inputs'. std::vector compute_hull(std::vector inputs) { sort(inputs.begin(), inputs.end()); std::vector hull; for (const Dish &p : inputs) { extend_hull(p, hull); } return hull; } vector solve(vector dishes, vector persons) { vector hull = compute_hull(dishes); vector preferred; for (int i = 0; i < persons.size(); ++i) { int64_t best = -1; int best_i = -1; for (const Dish &d : hull) { int64_t affinity = d.p[0] * persons[i].p[0] + d.p[1] * persons[i].p[1]; if (affinity > best || affinity == best && best_i > d.index) { best = affinity; best_i = d.index; } } preferred.push_back(best_i); } return preferred; } int main() { int N, M; cin >> N >> M; auto dishes = read_input(N); auto persons = read_input(M); vector preferred = solve(dishes, persons); for (int pref : preferred) { cout << pref + 1 << "\n"; } }