|
| 1 | +#include <bits/stdc++.h> //LATEX_IGNORED_LINE |
| 2 | +using namespace std; |
| 3 | + |
| 4 | +const int MXN = 1e5+100; |
| 5 | + |
| 6 | +struct Point { |
| 7 | + int x, y; |
| 8 | + |
| 9 | + bool const operator<(const Point& o) const { |
| 10 | + return make_tuple(x, y) < make_tuple(o.x, o.y); |
| 11 | + } |
| 12 | +}; |
| 13 | + |
| 14 | +struct AABB { |
| 15 | + int x1, y1, x2, y2; |
| 16 | + |
| 17 | + AABB() : x1(0), y1(0), x2(MXN), y2(MXN) {} |
| 18 | + AABB(int x1, int y1, int x2, int y2) : x1(x1), y1(y1), x2(x2), y2(y2) {} |
| 19 | + |
| 20 | + bool intersects(const AABB& other) const { |
| 21 | + bool overlap_x = (x1 <= other.x2) && (x2 >= other.x1); |
| 22 | + bool overlap_y = (y1 <= other.y2) && (y2 >= other.y1); |
| 23 | + return overlap_x && overlap_y; |
| 24 | + } |
| 25 | + |
| 26 | + bool contains(int x, int y) const { |
| 27 | + return (x >= x1 && x <= x2 && y >= y1 && y <= y2); |
| 28 | + } |
| 29 | + |
| 30 | + array<AABB, 4> subdivide() const { |
| 31 | + int x_center = x1 + (x2 - x1) / 2; |
| 32 | + int y_center = y1 + (y2 - y1) / 2; |
| 33 | + return { |
| 34 | + AABB{x1, y1, x_center, y_center}, // NW |
| 35 | + AABB{x_center, y1, x2, y_center}, // NE |
| 36 | + AABB{x1, y_center, x_center, y2}, // SW |
| 37 | + AABB{x_center, y_center, x2, y2} // SE |
| 38 | + }; |
| 39 | + } |
| 40 | +}; |
| 41 | + |
| 42 | + |
| 43 | +struct Circle { |
| 44 | + Point c; |
| 45 | + int r, w; |
| 46 | + AABB box; |
| 47 | + |
| 48 | + Circle(Point c, int r, int w) |
| 49 | + : c(c), r(r), w(w), box(c.x - r, c.y - r, c.x + r, c.y + r) {} |
| 50 | + |
| 51 | + bool const operator<(const Circle& o) const { |
| 52 | + return make_tuple(c.x, c.y, r) < make_tuple(o.c.x, o.c.y, o.r); |
| 53 | + } |
| 54 | +}; |
| 55 | + |
| 56 | +struct Square { |
| 57 | + Point p1, p2; |
| 58 | + int w; |
| 59 | + AABB box; |
| 60 | + |
| 61 | + Square(Point p1, Point p2) |
| 62 | + : p1(p1), p2(p2), box(min(p1.x, p2.x), min(p1.y, p2.y), |
| 63 | + max(p1.x, p2.x), max(p1.y, p2.y)) {} |
| 64 | + |
| 65 | + bool const operator<(const Square& o) const { |
| 66 | + return make_tuple(p1, p2) < make_tuple(o.p1, o.p2); |
| 67 | + } |
| 68 | +}; |
| 69 | + |
| 70 | +struct Triangle { |
| 71 | + Point p1, p2, p3; |
| 72 | + int w; |
| 73 | + AABB box; |
| 74 | + |
| 75 | + Triangle(Point p1, Point p2, Point p3) |
| 76 | + : p1(p1), p2(p2), p3(p3), |
| 77 | + box(min({p1.x, p2.x, p3.x}), min({p1.y, p2.y, p3.y}), max({p1.x, p2.x, p3.x}), max({p1.y, p2.y, p3.y})) {} |
| 78 | + |
| 79 | + bool const operator<(const Triangle& o) const { |
| 80 | + return make_tuple(p1, p2, p3) < make_tuple(o.p1, o.p2, o.p3); |
| 81 | + } |
| 82 | +}; |
| 83 | + |
| 84 | +template <typename T> |
| 85 | +class Quadtree { |
| 86 | + public: |
| 87 | + static const int MIN_OBJECTS = 8; |
| 88 | + static const int MAX_DEPTH = 16; |
| 89 | + |
| 90 | + Quadtree(const AABB& root_bounds, const vector<T>& all_objects) |
| 91 | + : bounds(root_bounds), depth(0) { |
| 92 | + |
| 93 | + vector<const T*> object_ptrs; |
| 94 | + object_ptrs.reserve(all_objects.size()); |
| 95 | + for (const auto& obj : all_objects) { |
| 96 | + object_ptrs.push_back(&obj); |
| 97 | + } |
| 98 | + |
| 99 | + build(object_ptrs); |
| 100 | + } |
| 101 | + |
| 102 | + const vector<const T*>& query(int x, int y) const { |
| 103 | + const Quadtree* node = this; |
| 104 | + |
| 105 | + while (node->is_branch) { |
| 106 | + int child_index = node->get_child_index(x, y); |
| 107 | + if (child_index == -1) break; |
| 108 | + node = node->children[child_index].get(); |
| 109 | + } |
| 110 | + |
| 111 | + return node->objects; |
| 112 | + } |
| 113 | + |
| 114 | + private: |
| 115 | + AABB bounds; |
| 116 | + int depth; |
| 117 | + bool is_branch = false; |
| 118 | + int x_center, y_center; |
| 119 | + |
| 120 | + array<unique_ptr<Quadtree<T>>, 4> children; |
| 121 | + |
| 122 | + vector<const T*> objects; |
| 123 | + |
| 124 | + Quadtree(const AABB& box, int d) : bounds(box), depth(d) {} |
| 125 | + |
| 126 | + void build(const vector<const T*>& parent_objects) { |
| 127 | + x_center = bounds.x1 + (bounds.x2 - bounds.x1) / 2; |
| 128 | + y_center = bounds.y1 + (bounds.y2 - bounds.y1) / 2; |
| 129 | + |
| 130 | + for (const T* obj : parent_objects) { |
| 131 | + if (bounds.intersects(obj->box)) { |
| 132 | + objects.push_back(obj); |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + if (objects.size() > MIN_OBJECTS && depth < MAX_DEPTH) { |
| 137 | + is_branch = true; |
| 138 | + auto child_bounds = bounds.subdivide(); |
| 139 | + |
| 140 | + for (int i = 0; i < 4; ++i) { |
| 141 | + children[i] = unique_ptr<Quadtree<T>>(new Quadtree<T>(child_bounds[i], depth + 1)); |
| 142 | + children[i]->build(objects); |
| 143 | + } |
| 144 | + |
| 145 | + objects.clear(); |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + int get_child_index(int x, int y) const { |
| 150 | + if (y <= y_center) return (x <= x_center) ? 0 : 1; // 0 (NW) ou 1 (NE) |
| 151 | + else return (x <= x_center) ? 2 : 3; // 2 (SW) ou 3 (SE) |
| 152 | + } |
| 153 | +}; |
0 commit comments