Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- struct point
- {
- long long x, y, ind;
- };
- struct segment
- {
- point left, right;
- };
- long long triangle_area (point a, point b, point c)
- {
- return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
- }
- bool clockwise (point a, point b, point c) {
- return triangle_area (a, b, c) <= 0;
- }
- bool counter_clockwise (point a, point b, point c) {
- return triangle_area (a, b, c) >= 0;
- }
- bool is_under(point z, segment a)
- {
- if (z.x < a.left.x || z.x > a.right.x)
- return false;
- return counter_clockwise(z, a.right, a.left);
- }
- bool is_above(point z, segment a)
- {
- if (z.x < a.left.x || z.x > a.right.x)
- return false;
- return clockwise(z, a.right, a.left);
- }
- bool in_segment(point z, segment a)
- {
- return is_above(z, a) && is_under(z, a);
- }
- bool cmp_x(point & a, point & b)
- {
- return a.x < b.x || a.x == b.x && a.y < b.y;
- }
- bool cmp_seg(segment & a, segment & b)
- {
- return a.left.x < b.left.x || a.left.x == b.left.x && a.right.x < b.right.x;
- }
- bool is_equal(segment a, segment b)
- {
- return (a.left.x == b.left.x && a.left.y == b.left.y && a.right.x == b.right.x && a.right.y == b.right.y);
- }
- bool cmp_pair(pair <point, int> & a, pair < point, int> & b)
- {
- if (a.first.x < b.first.x)
- return true;
- if (a.first.x > b.first.x)
- return false;
- int a_sec = a.second;
- int b_sec = b.second;
- if (a_sec >= 0)
- a_sec %= 2;
- if (b_sec >= 0)
- b_sec %=2;
- if (a_sec != b_sec)
- return b_sec < a_sec;
- return (a.first.y < b.first.y);
- }
- bool is_under(segment a, segment b)
- {
- if (a.left.x == b.left.x)
- {
- if (a.left.y != b.left.y)
- return a.left.y < b.left.y;
- return (is_under(a.right, b) || is_above(b.right, a));
- }
- if (a.right.x == b.right.y)
- {
- if (a.right.y != b.right.y)
- return a.right.y < b.right.y;
- return(is_under(a.left, b) || is_above(b.left, a));
- }
- return (is_under(a.left, b) || is_under(a.right, b) ||
- is_above(b.left, a) || is_above(b.right, a));
- }
- bool is_above(segment a, segment b)
- {
- if (a.left.x == b.left.x)
- {
- if (a.left.y != b.left.y)
- return a.left.y > b.left.y;
- return (is_above(a.right, b) || is_under(b.right, a));
- }
- if (a.right.x == b.right.y)
- {
- if (a.right.y != b.right.y)
- return a.right.y > b.right.y;
- return(is_above(a.left, b) || is_under(b.left, a));
- }
- return (is_above(a.left, b) || is_above(a.right, b) ||
- is_under(b.left, a) || is_under(b.right, a));
- }
- int n;
- const int MAXN = 1e5+1e3;
- const long long INF = 2*1e18 + 1e9;
- segment segments[MAXN];
- string ans[MAXN];
- //treap
- //###########################################################################
- struct Node {
- int key, sz, val;
- Node *l, *r;
- };
- Node* root;
- Node* new_node(int val)
- {
- Node *result = new Node;
- result->key = rand();
- result->sz = 1;
- result->val = val;
- result->l = result->r = nullptr;
- return result;
- }
- int get_sz(Node *t)
- {
- if (t == nullptr) { return 0; }
- return t->sz;
- }
- void upd_sz(Node *t)
- {
- if (t == nullptr) { return; }
- t->sz = 1 + get_sz(t->l) + get_sz(t->r);
- }
- Node *merge(Node* t1, Node *t2)
- {
- if (t1 == nullptr) { return t2; }
- if (t2 == nullptr) { return t1; }
- if (t1->key > t2->key)
- {
- t1->r = merge(t1->r, t2);
- upd_sz(t1);
- return t1;
- }
- else
- {
- t2->l = merge(t1, t2->l);
- upd_sz(t2);
- return t2;
- }
- }
- void split(Node *t, int x, Node *&t1, Node *&t2)
- {
- if (t == nullptr)
- {
- t1 = t2 = nullptr;
- return;
- }
- if (get_sz(t->l) < x)
- {
- split(t->r, x - get_sz(t->l) - 1, t->r, t2);
- t1 = t;
- }
- else
- {
- split(t->l, x, t1, t->l);
- t2 = t;
- }
- upd_sz(t);
- }
- Node *add(Node *t, int pos, int val)
- {
- Node *t1, *t2;
- split(t, pos, t1, t2);
- Node* new_tree = new_node(val);
- return merge(merge(t1, new_tree), t2);
- }
- Node* erase(Node *t, int pos)
- {
- cout << get_sz(root) << " 77777777\n";
- Node *t1, *t2, *t3, *t4;
- split(t, pos, t1, t2);
- split(t2, pos + 1, t3, t4);
- t = merge(t1, t4);
- delete t3;
- return t;
- }
- int get(Node *t, int pos)
- {
- int my_idx = get_sz(t->l);
- if (pos < my_idx)
- {
- return get(t->l, pos);
- }
- else if (pos == my_idx)
- {
- return t->val;
- }
- else
- {
- return get(t->r, pos - my_idx - 1);
- }
- }
- //#####################################################################
- void add_segment(int ind)
- {
- int sz = get_sz(root);
- if (sz == 1)
- {
- segment seg = segments[get(root, 0)];
- if (is_under(segments[ind], seg))
- root = add(root, 0, ind);
- else
- root = add(root, 1, ind);
- return;
- }
- if (sz == 0)
- {
- root = add(root, 0, ind);
- return;
- }
- int l = 0; int r = sz - 1;
- segment l_seg = segments[get(root, l)];
- segment r_seg = segments[get(root, r)];
- if (is_under(segments[ind], l_seg))
- {
- root = add(root, 0, ind);
- return;
- }
- if (is_above(segments[ind], r_seg))
- {
- root = add(root, r + 1, ind);
- return;
- }
- while (l < r - 1)
- {
- int md = (l + r) / 2;
- segment md_seg = segments[get(root, md)];
- if (is_under(segments[ind], md_seg))
- r = md;
- else
- l = md;
- }
- root = add(root, l + 1, ind);
- }
- void delete_segment(int ind)
- {
- //cout << get_sz(root) << " 77777777\n";
- if(get_sz(root) == 1)
- {
- root = erase(root, 0);
- return;
- }
- int l = 0; int r = get_sz(root) - 1;
- segment l_seg = segments[get(root, 0)];
- segment r_seg = segments[get(root, r)];
- if (is_equal(segments[ind], l_seg))
- {
- root = erase(root, 0);
- return;
- }
- if (is_equal(segments[ind], r_seg))
- {
- root = erase(root, r);
- return;
- }
- while (l < r - 1)
- {
- int md = (l + r) / 2;
- segment md_seg = segments[get(root, md)];
- if (is_under(segments[ind], md_seg))
- r = md;
- else
- l = md;
- }
- r_seg = segments[get(root, r)];
- if (is_equal(segments[ind], r_seg))
- {
- root = erase(root, r);
- return;
- }
- root = erase(root, l);
- }
- int fnd_inter_cnt(point x)
- {
- if (get_sz(root) == 0)
- return 0;
- int l = 0; int r = get_sz(root) - 1;
- int sz = r + 1;
- cout << sz << '\n';
- cout << "point x:" << x.x << ' ' << x.y <<'\n';
- point lf = segments[get(root, l)].left;
- point rf = segments[get(root, l)].right;
- cout << "first segment" << lf.x << ' ' << lf.y << ' ' << rf.x << ' ' << rf.y << '\n';
- lf = segments[get(root, r)].left;
- rf = segments[get(root, r)].right;
- cout << "second segment" << lf.x << ' ' << lf.y << ' ' << rf.x << ' ' << rf.y << '\n';
- cout << "######\n";
- if (!is_under(x, segments[get(root, r)]) || !is_above(x, segments[get(root, l)]))
- return 0;
- while (l < r - 1)
- {
- int md = (l + r) / 2;
- segment md_seg = segments[get(root, md)];
- if (is_above(x, md_seg))
- l = md;
- else
- r = md;
- }
- //cout << "here\n";
- if (in_segment(x, segments[get(root, l)]) || in_segment(x, segments[get(root, r)]))
- return -1;
- return sz - r;
- }
- void affine_transformation(vector<point>* v, int a, int b, int c, int d)
- {
- for (int i = 0; i < (*v).size(); i++)
- {
- long long x = (*v)[i].x, y = (*v)[i].y;
- (*v)[i].x = a * x + b * y;
- (*v)[i].y = c * x + d * y;
- }
- }
- void fnd_locations(vector <point> queries)
- {
- vector <pair < point, int > > points;
- for (int i = 0; i < n; i++)
- {
- points.push_back({segments[i].left, 2 * i});
- points.push_back({segments[i].right, 2 * i + 1});
- }
- int k = queries.size();
- for (int i = 0; i < k; i++)
- points.push_back({queries[i], -1});
- sort(points.begin(), points.end(), &cmp_pair);
- /*
- for (int i = 0; i < points.size(); i++)
- {
- cout << points[i].first.x << ' ' << points[i].first.y << ' ' << points[i].second << '\n';
- }
- */
- for (int i = 0; i < points.size(); i++)
- {
- auto cur = points[i];
- if (cur.second == -1)
- {
- int inter_cnt = fnd_inter_cnt(cur.first);
- if (inter_cnt % 2 == 1)
- ans[cur.first.ind] = "INSIDE";
- if (inter_cnt % 2 == 0)
- ans[cur.first.ind] = "OUTSIDE";
- if (inter_cnt == -1)
- ans[cur.first.ind] = "BORDER";
- }
- if (cur.second != -1 && cur.second % 2 == 0)
- {
- add_segment(cur.second / 2);
- }
- if (cur.second != -1 && cur.second % 2 == 1)
- {
- delete_segment(cur.second / 2);
- }
- }
- }
- int solve()
- {
- root = nullptr;
- cin >> n;
- vector<point> v;
- for (int i = 0; i < n; i++)
- {
- int x, y;
- cin >> x >> y;
- v.push_back({x, y, i});
- }
- int k;
- cin >> k;
- vector <point> queries;
- for (int i = 0; i < k; i++)
- {
- int x, y;
- cin >> x >> y;
- queries.push_back({x, y, i});
- }
- affine_transformation(&v, 1, 1, 0, 1);
- affine_transformation(&queries, 1, 1, 0, 1);
- //sort(queries.begin(), queries.end(), &cmp_x);
- for (int i = 0; i < n - 1; i++)
- {
- if (v[i].x < v[i + 1].x || v[i].x == v[i + 1].x && v[i].y < v[i + 1].y)
- segments[i] = {v[i], v[i + 1]};
- else
- segments[i] = {v[i + 1], v[i]};
- }
- if (v[0].x < v[n - 1].x || v[0].x == v[n - 1].x && v[0].y < v[n - 1].y)
- segments[n - 1] = {v[0], v[n - 1]};
- else
- segments[n - 1] = {v[n - 1], v[0]};
- //sort(segments, segments + n, &cmp_seg);
- fnd_locations(queries);
- for (int i = 0; i < k; i++)
- cout << ans[i] <<'\n';
- }
- int main()
- {
- int t;
- cin >> t;
- while (t > 0)
- {
- t--;
- solve();
- cout <<'\n';
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement