Submission #956280

#TimeUsernameProblemLanguageResultExecution timeMemory
956280chrisvilchesDragon 2 (JOI17_dragon2)C++14
100 / 100
2512 ms3672 KiB
#include <bits/stdc++.h> using namespace std; struct Point { int x, y, idx; Point operator-(const Point& p) const { return {x - p.x, y - p.y, idx}; } Point operator+(const Point& p) const { return {x + p.x, y + p.y, idx}; } long long cross(const Point& p) const { return x * (long long)p.y - y * (long long)p.x; } Point negate() const { return {-x, -y, idx}; } }; short orientation(const Point& o, const Point& a, const Point& b) { const long long x = (a - o).cross(b - o); return (x > 0) - (x < 0); } Point A, B; vector<int> mid_it; bool above(const Point& p) { return B.cross(p) > 0; } Point to_upper(const Point& p) { return above(p) ? p : p.negate(); } bool operator<(const Point& p, const Point& q) { return to_upper(p).cross(to_upper(q)) > 0; } bool cmp_by_b(const Point& p, const Point& q) { const bool a1 = above(p); const bool a2 = above(q); if (a1 != a2) return a1; return p.cross(q) > 0; } int query(const vector<Point>& points1, const vector<Point>& points2, const vector<Point>& ord_b, const int attacked_idx) { if (points1.empty() || points2.empty()) return 0; int total = 0; int events[]{0, 0}; int j = 0; for (const Point& p : points1) { while (j < (int)points2.size()) { const Point& q = points2[j]; if (p < q) break; events[above(q)]++; j++; } const auto mid = ord_b.begin() + mid_it[attacked_idx]; if (above(p)) { const auto it = lower_bound(mid, ord_b.end(), B - p, cmp_by_b); const int count = it - mid; total += count - events[0]; for (auto it = mid == ord_b.end() ? mid - 1 : mid;; it--) { const Point q = *it + B; total += above(q) && p.cross(q) < 0 && orientation(B, p, q) > 0; if (it == ord_b.begin()) break; } } else { const auto it = lower_bound(ord_b.begin(), mid, B - p, cmp_by_b); const int count = it - ord_b.begin(); total += events[1] - count; for (auto it = mid; it != ord_b.end(); it++) { const Point q = *it + B; total += p.cross(q) > 0 && orientation(B, p, q) < 0; } } } return total; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int N, M, Q; while (cin >> N >> M) { vector<vector<Point>> tribe_points(M + 1); vector<vector<Point>> order_by_b(M + 1); mid_it.resize(M + 1); for (int i = 0; i < N; i++) { Point p; int tribe; cin >> p.x >> p.y >> tribe; tribe_points[tribe].push_back(p); } cin >> A.x >> A.y; cin >> B.x >> B.y; cin >> Q; B = B - A; for (int m = 0; m <= M; m++) { auto& points = tribe_points[m]; for (auto& p : points) p = p - A; for (auto& p : points) p = p - B; sort(points.begin(), points.end(), cmp_by_b); for (int i = 0; i < (int)points.size(); i++) points[i].idx = i; auto& b = order_by_b[m]; b = points; mid_it[m] = lower_bound(b.begin(), b.end(), B.negate(), cmp_by_b) - b.begin(); for (auto& p : points) p = p + B; sort(points.begin(), points.end()); } while (Q--) { int i, j; cin >> i >> j; cout << query(tribe_points[i], tribe_points[j], order_by_b[j], j) << '\n'; } } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...