Challenge: Geometry Queries
Scor cont: 100.0 / 100
Submission status: Accepted
Submission score: 1.0
Submission ID: 464814878
Limbaj: cpp14
Link challenge: https://www.hackerrank.com/challenges/geometry-queries/problem
Cerinta
There are $N$ lines. Each line has an index between $1$ and $N$. The slope of each line is negative, i.e. it goes from upper-left to lower-right.
There are $Q$ queries. Each of them is in the format `L R x y`, and you should output whether there is any line with index between $L$ and $R$ and the point $(x, y)$ is under it. If there is, then the answer is `YES`, otherwise `NO`.
As you know, any line splits an infinite plane into two regions. The point $(x,y)$ is under the line if that point is at the same region with point $(-\infty, -\infty)$. If the point lies on the line it does not count.
**Input Format**
The first line contains $N$, the number of lines. The following $N$ lines each contains two integers $m$ and $n$ that describes the line $mx + n = y$.
The next line contains $Q$, the number of queries. Each subsequent line contains 4 integers $L, R, x, y$.
**Output Format**
For each query, output one line containing either `YES` or `NO`.
**Constraints**
$1 \leq N \leq 10^5$ (Number of lines)
$1 \leq Q \leq 10^5$ (Number of queries)
$-10^9 \leq x \leq 10^9$
$-10^9 \leq y \leq 10^9$
$-10^9 \leq m < 0$
$-10^9 \leq n \leq 10^9$
$1 \leq L \leq R \leq N$
**Sample Input**
2
-1 3
-2 -4
3
1 2 0 0
1 1 0 0
2 2 0 0
**Sample Output**
YES
YES
NO
**Explanation**
The image shows the two lines of the sample input.
<a href="http://hizliresim.com/JEYqEQ"><img src="http://i.hizliresim.com/JEYqEQ.png" /></a>
<sub>Time Limits: C/C++ 1 sec, Java/C# 2 sec, other languages follow standard TL given in [Environment](https://hackerrank.com/environment)</sub>
Cod sursa
#include <bits/stdc++.h>
using namespace std;
struct Line {
long long m, b; // y = m*x + b
};
static inline __int128 eval128(const Line& l, long long x) {
return (__int128)l.m * x + l.b;
}
// Given sorted by slope increasing and unique slope, build upper hull.
static vector<Line> buildHull(const vector<Line>& lines) {
vector<Line> hull;
hull.reserve(lines.size());
auto bad = [&](const Line& a, const Line& b, const Line& c) -> bool {
// x_inter(a,b) >= x_inter(b,c)
// (a.b - b.b)/(b.m-a.m) >= (b.b - c.b)/(c.m-b.m)
// denominators > 0 (strictly increasing slopes)
__int128 left = (__int128)(a.b - b.b) * (c.m - b.m);
__int128 right = (__int128)(b.b - c.b) * (b.m - a.m);
return left >= right;
};
for (const Line& ln : lines) {
while (hull.size() >= 2 && bad(hull[hull.size() - 2], hull[hull.size() - 1], ln)) {
hull.pop_back();
}
hull.push_back(ln);
}
return hull;
}
// Merge two slope-sorted hull vectors, deduplicate same slope by higher intercept.
static vector<Line> mergeBySlope(const vector<Line>& A, const vector<Line>& B) {
vector<Line> tmp;
tmp.reserve(A.size() + B.size());
size_t i = 0, j = 0;
while (i < A.size() || j < B.size()) {
Line pick;
if (j == B.size() || (i < A.size() && A[i].m < B[j].m)) {
pick = A[i++];
} else if (i == A.size() || B[j].m < A[i].m) {
pick = B[j++];
} else {
// equal slope, keep bigger intercept
pick = (A[i].b >= B[j].b) ? A[i] : B[j];
++i;
++j;
}
if (!tmp.empty() && tmp.back().m == pick.m) {
if (pick.b > tmp.back().b) tmp.back().b = pick.b;
} else {
tmp.push_back(pick);
}
}
return tmp;
}
static __int128 queryHull(const vector<Line>& hull, long long x) {
int l = 0, r = (int)hull.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (eval128(hull[mid], x) <= eval128(hull[mid + 1], x)) l = mid + 1;
else r = mid;
}
return eval128(hull[l], x);
}
int n;
vector<Line> arr;
vector<vector<Line>> seg;
void build(int idx, int l, int r) {
if (l == r) {
seg[idx] = {arr[l]};
return;
}
int mid = (l + r) >> 1;
build(idx << 1, l, mid);
build(idx << 1 | 1, mid + 1, r);
vector<Line> merged = mergeBySlope(seg[idx << 1], seg[idx << 1 | 1]);
seg[idx] = buildHull(merged);
}
__int128 negInf() {
return -((__int128)1 << 120);
}
__int128 query(int idx, int l, int r, int ql, int qr, long long x) {
if (qr < l || r < ql) return negInf();
if (ql <= l && r <= qr) return queryHull(seg[idx], x);
int mid = (l + r) >> 1;
__int128 a = query(idx << 1, l, mid, ql, qr, x);
__int128 b = query(idx << 1 | 1, mid + 1, r, ql, qr, x);
return (a > b ? a : b);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
arr.resize(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> arr[i].m >> arr[i].b;
}
seg.assign(4 * (n + 5), {});
build(1, 1, n);
int q;
cin >> q;
while (q--) {
int L, R;
long long x, y;
cin >> L >> R >> x >> y;
__int128 mx = query(1, 1, n, L, R, x);
if (mx > (__int128)y) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
HackerRank Geometry – Geometry Queries
