Editorial for Classification Problem
Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.
Submitting an official solution before solving the problem yourself is a bannable offence.
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2")
#include <bits/stdc++.h>
using namespace std;
int binarySearch(vector<pair<long double, pair<int, int>>>& array, int search)
{
int start = 0;
int end = array.size() - 1;
while (start <= end)
{
int middle = start + (end - start) / 2;
assert(array[middle].first != search);
if (array[middle].first > search)
end = middle - 1;
if (array[middle].first < search)
start = middle + 1;
}
if (start == array.size())
return array[array.size() - 1].second.second;
else
return array[start].second.first;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
pair<int, int> parabola[n];
for (int index = 0; index < n; index++)
cin >> parabola[index].first >> parabola[index].second;
pair<long double, int> order[n];
for (int index = 0; index < n; index++)
order[index] = {1.0l * parabola[index].first / 2, index};
sort(order, order + n);
vector<int> absOrder;
for (int index = 0, nextIndex = 1; index < n; index = nextIndex++)
{
pair<int, int> max = {parabola[order[index].second].second, order[index].second};
while (nextIndex < n && order[index].first == order[nextIndex].first)
{
if (parabola[order[nextIndex].second].second > max.first)
max = {parabola[order[nextIndex].second].second, order[nextIndex].second};
nextIndex++;
}
absOrder.emplace_back(max.second);
}
list<pair<long double, pair<int, int>>> intersection;
for (int index = 1; index < absOrder.size(); index++)
{
long double intersectionPoint = 1.0l * (parabola[absOrder[index]].second - parabola[absOrder[index - 1]].second) / (parabola[absOrder[index - 1]].first - parabola[absOrder[index]].first);
intersection.emplace_back(intersectionPoint, make_pair(absOrder[index - 1], absOrder[index]));
}
revise:
{
bool final = true;
auto curr = intersection.begin();
for (auto prev = intersection.begin()++; curr != intersection.end(); prev = curr++)
if (prev -> first > curr -> first)
{
int leftparabola = prev -> second.first, rightparabola = curr -> second.second;
long double intersectionPoint = 1.0l * (parabola[rightparabola].second - parabola[leftparabola].second) / (parabola[leftparabola].first - parabola[rightparabola].first);
prev = intersection.erase(prev);
curr = intersection.erase(prev);
prev = intersection.emplace(curr, intersectionPoint, make_pair(leftparabola, rightparabola));
curr = prev--;
final = false;
}
if (!final)
goto revise;
};
vector<pair<long double, pair<int, int>>> absIntersection;
for (auto element : intersection)
absIntersection.emplace_back(element);
while (q--)
{
int x;
cin >> x;
if (absIntersection.empty())
cout << absOrder.front() + 1 << '\n';
else
cout << binarySearch(absIntersection, x) + 1 << '\n';
}
return 0;
}