Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <limits.h>
- #include <vector>
- #include <iostream>
- #include <set>
- #include<random>
- #include <algorithm>
- struct Point {
- long long x, y;
- Point() {
- x = 0;
- y = 0;
- }
- Point(long long a, long long b) {
- x = a;
- y = b;
- }
- };
- Point operator +(const Point pt1, const Point pt2) {
- return Point(pt1.x + pt2.x, pt1.y + pt2.y);
- }
- Point operator -(const Point pt1, const Point pt2) {
- return Point(pt1.x - pt2.x, pt1.y - pt2.y);
- }
- Point operator *(const Point pt, long long x) {
- return Point(pt.x * x, pt.y * x);
- }
- int operator *(const Point pt1, const Point pt2) {
- return pt1.x * pt2.x + pt1.y * pt2.y;
- }
- long long operator ^(const Point pt1, const Point pt2) {
- return pt1.x * pt2.y - pt1.y * pt2.x;
- }
- bool AreEquel(Point pt1, Point pt2) {
- return pt1.x == pt2.x && pt1.y == pt2.y;
- }
- struct Segment {
- Point one;
- Point two;
- Segment() {
- one = { 0, 0 };
- two = { 0, 0 };
- }
- Segment(Point x, Point y) {
- one = x;
- two = y;
- }
- Point less() {
- if (one.x < two.x || (one.x == two.x && one.y < two.y)) return one;
- return two;
- }
- Point more() {
- if (one.x < two.x || (one.x == two.x && one.y < two.y)) return two;
- return one;
- }
- };
- int Check(Segment* s, Point cur) {
- Segment t = *s;
- long long where_situated = ((cur - t.less()) ^ (t.more() - t.less()));
- if (where_situated > 0) return -1;
- if (where_situated == 0) return 0;
- return 1;
- }
- bool CheckSegments(Segment* one, Segment* two) {
- Segment first = *one, second = *two;
- Point cur = second.less();
- long long where_situated = ((cur - first.less()) ^ (first.more() - first.less()));
- if (where_situated > 0) return true;
- if (where_situated == 0 && ((second.more() - cur) ^ (first.more() - first.less())) >= 0) return true;
- return false;
- }
- struct Event {
- int type;
- int num;
- Point p;
- };
- std::mt19937 rnd;
- int Mod = 1e9 + 7;
- class Cartesian_Tree {
- public:
- Cartesian_Tree() {
- root = Empty;
- }
- void Insert(Segment *s) {
- Insert(root, s);
- }
- void Erase(Point p) {
- Erase(root, p);
- }
- int FindNumSegmentsMore(Point p) {
- return FindNumSegmentsMore(root, p, 0);
- }
- private:
- struct node {
- node* left;
- node* right;
- Segment* key;
- int pr;
- int size;
- };
- node* Empty = new node{ NULL, NULL, NULL, 0, 0 };
- node* root;
- void Update(node* &v) {
- v->size = v->left->size + v->right->size + 1;
- }
- std::pair<node*, node*> Split(node* root, Segment* key) {
- if (root == Empty) return{ Empty, Empty };
- if (CheckSegments(root->key, key)) {
- std::pair<node*, node*> now = Split(root->left, key);
- root->left = now.second;
- Update(root);
- return{ now.first, root };
- }
- else {
- std::pair<node*, node*> now = Split(root->right, key);
- root->right = now.first;
- Update(root);
- return{ root, now.second };
- }
- }
- node* Merge(node* left, node* right) {
- if (left == Empty) return right;
- if (right == Empty) return left;
- if (left->pr < right->pr) {
- node* now = Merge(left->right, right);
- left->right = now;
- Update(now);
- Update(left);
- return left;
- }
- else {
- node* now = Merge(left, right->left);
- right->left = now;
- Update(now);
- Update(right);
- return right;
- }
- }
- void Insert(node* &root, Segment* s) {
- std::pair<node*, node*> now = Split(root, s);
- root = Merge(Merge(now.first, new node{ Empty, Empty, s, rand() % Mod, 1 }), now.second);
- }
- void Erase(node* &root, Point cur) {
- if (root == Empty) {
- return;
- }
- int where_situated = Check(root->key, cur);
- if (where_situated == 0) {
- root = Merge(root->left, root->right);
- return;
- }
- if (where_situated == -1) Erase(root->left, cur);
- else Erase(root->right, cur);
- Update(root);
- return;
- }
- int FindNumSegmentsMore(node*v, Point p, int cur_intersect) {
- if (v == Empty) return cur_intersect;
- int f = Check(v->key, p);
- if (f == 0) return -1;
- if (f == -1) { return FindNumSegmentsMore(v->left, p, cur_intersect); }
- return FindNumSegmentsMore(v->right, p, cur_intersect + v->left->size + 1);
- }
- };
- bool comp(Event one, Event two) {
- if (one.p.x < two.p.x) return true;
- if (one.p.x > two.p.x) return false;
- if (one.type < two.type) return true;
- if (one.type > two.type) return false;
- if (one.p.y < two.p.y) return true;
- if (one.p.y > two.p.y) return false;
- if (one.num < two.num) return true;
- return false;
- }
- class Solve {
- public:
- Solve() {
- count_of_vertex = 0;
- count_of_points = 0;
- e = 10000;
- polygon.resize(0);
- edge.resize(0);
- }
- void solution() {
- read();
- solve();
- write();
- }
- private:
- int count_of_vertex;
- int count_of_points;
- long long e;
- std::vector<Point> polygon;
- std::set<std::pair<int, int>> vertexs;
- std::vector<Segment> edge;
- std::vector<Point> points;
- std::vector<int> ans;
- void add(Point cur) {
- if (polygon.size() > 0 && AreEquel(polygon.back(), cur)) return;
- if (polygon.size() > 0) {
- edge.push_back(Segment(polygon.back(), cur));
- }
- polygon.push_back(cur);
- vertexs.insert({ cur.x, cur.y });
- }
- void ChangeEdge(int i) {
- Point cur = polygon[i];
- polygon[i] = { cur.x * e + cur.y, cur.y };
- vertexs.insert({ cur.x * e + cur.y, cur.y });
- if (i > 0) {
- edge.push_back({ polygon[i - 1], polygon[i] });
- }
- }
- void CheckEvent(Cartesian_Tree& tree, Event now) {
- //std::cout << now.type << ' ' << now.p.x << ' ' << now.p.y << ' ' << now.num << '\n';
- if (now.type == 0) {
- tree.Insert(&edge[now.num]);
- }
- if (now.type == -1) {
- tree.Erase(now.p);
- }
- if (now.type == 1) {
- if (vertexs.find({ now.p.x, now.p.y }) != vertexs.end()) {
- ans[now.num] = 0;
- return;
- }
- int intersections = tree.FindNumSegmentsMore(now.p);
- if (intersections == -1) {
- ans[now.num] = 0;
- }
- else {
- if (intersections % 2 == 0) {
- ans[now.num] = -1;
- }
- else {
- ans[now.num] = 1;
- }
- }
- }
- }
- void read() {
- std::cin >> count_of_vertex;
- for (int i = 0; i < count_of_vertex; i++) {
- long long x, y;
- std::cin >> x >> y;
- Point cur = { x * e + y, y };
- add(cur);
- }
- if (AreEquel(polygon.back(), polygon[0])) {
- polygon.pop_back();
- }
- edge.push_back(Segment(polygon.back(), polygon[0]));
- count_of_vertex = polygon.size();
- std::cin >> count_of_points;
- points.resize(count_of_points);
- for (int i = 0; i < count_of_points; i++) {
- long long x, y;
- std::cin >> x >> y;
- Point cur = { x * e + y, y };
- points[i] = cur;
- }
- ans.resize(count_of_points);
- }
- void solve() {
- std::vector<Event> events;
- for (int i = 0; i < count_of_vertex; i++) {
- events.push_back({ 0, i, edge[i].less() });
- events.push_back({ -1, i, edge[i].more() });
- }
- for (int i = 0; i < count_of_points; i++) {
- events.push_back({ 1, i, points[i] });
- }
- sort(events.begin(), events.end(), comp);
- Cartesian_Tree tree = Cartesian_Tree();
- for (int i = 0; i < events.size(); i++) {
- CheckEvent(tree, events[i]);
- }
- }
- void write() {
- for (int i = 0; i < count_of_points; i++) {
- if (ans[i] == -1) {
- std::cout << "OUTSIDE" << '\n';
- }
- if (ans[i] == 0) {
- std::cout << "BORDER" << '\n';
- }
- if (ans[i] == 1) {
- std::cout << "INSIDE" << '\n';
- }
- }
- }
- };
- int main() {
- int t;
- std::cin >> t;
- for (int i = 0; i < t; i++) {
- Solve solut = Solve();
- solut.solution();
- }
- system("pause");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement