Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <set>
- #include <map>
- #include <bitset>
- #include <deque>
- #include <queue>
- #include <string>
- #include <algorithm>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <ctime>
- #include <cmath>
- #include <cassert>
- #include <complex>
- #define pb push_back
- #define pbk pop_back
- #define sz(a) ((int) (a).size())
- #define all(a) (a).begin(), (a).end()
- #define mp make_pair
- #define fs first
- #define sc second
- #define next _next
- #define prev _prev
- #define link _link
- #define hash _hash
- #ifdef LOCAL42
- #define eprintf(...) fprintf(stderr, __VA_ARGS__)
- #else
- #define eprintf(...) 42
- #endif
- #if _WIN32 || __WIN32__ || _WIN64 || __WIN64__
- #define LLD "%I64d"
- #else
- #define LLD "%lld"
- #endif
- using namespace std;
- typedef long long ll;
- typedef unsigned int uint;
- typedef unsigned long long ull;
- typedef long double ld;
- typedef vector<int> vi;
- typedef pair<int, int> pii;
- const int inf = 1e9;
- const double eps = 1e-9;
- const double pi = 4 * atan(1.0);
- const int N = int(2e5) + 100;
- const int SIZE = int(1e6) + 100;
- struct point {
- int x, y;
- point() {}
- point(int x, int y) : x(x), y(y) {}
- };
- point operator - (const point& a, const point& b) {
- return point(a.x - b.x, a.y - b.y);
- }
- point operator + (const point& a, const point& b) {
- return point(a.x + b.x, a.y + b.y);
- }
- inline ll vec(const point& a, const point& b) {
- return 1LL * a.x * b.y - 1LL * b.x * a.y;
- }
- inline int half(const point& p) {
- if (p.x > 0 || (p.x == 0 && p.y > 0)) {
- return 0;
- }
- return 1;
- }
- bool operator < (const point& a, const point& b) {
- int ha = half(a), hb = half(b);
- if (ha != hb) {
- return ha < hb;
- }
- ll v = vec(a, b);
- if (v != 0) {
- return v > 0;
- }
- return mp(a.x, a.y) < mp(b.x, b.y);
- }
- bool operator == (const point& a, const point& b) {
- return a.x == b.x && a.y == b.y;
- }
- const int QUERY = 0;
- const int DEL = 1;
- const int ADD = 2;
- struct event {
- int x, t, num, bal;
- event() {}
- event(int x, int t, int num, int bal) : x(x), t(t), num(num), bal(bal) {}
- };
- bool operator < (const event& a, const event& b) {
- if (a.x != b.x) {
- return a.x < b.x;
- }
- return a.t < b.t;
- }
- struct node {
- int num, bal, sum_bal, h, p, l, r;
- };
- int n, m, k, cur = 0;
- point p[N], q[N];
- bool used[N], is_bridge[N];
- int u[N], v[N], tin[N], tout[N];
- set<pii> edges;
- vector<pii> lst;
- map<pii, int> num;
- set<int> xs;
- vector<pii> neig[N];
- bool ans[N];
- vector<pair<point, int> > g[N];
- vector<pair<point, point> > segs;
- vector<event> events;
- node d[SIZE];
- int node_num[SIZE];
- inline int get_rand(int l, int r) {
- return l + rand() % (r - l + 1);
- }
- inline void rotate() {
- for (;;) {
- //cerr << "IT" << endl;
- int a = get_rand(-1000, 1000), b = get_rand(-1000, 1000);
- int c = get_rand(-1000, 1000), d = get_rand(-1000, 1000);
- //int a = 4243, b = 1279;
- //int c = -3516, d = 5757;
- if (a * d - b * c == 0) {
- //assert(false);
- continue;
- }
- xs.clear();
- bool good = true;
- for (int i = 0; i < m; ++i) {
- int x1 = a * p[u[i]].x + b * p[u[i]].y;
- int x2 = a * p[v[i]].x + b * p[v[i]].y;
- if (x1 == x2) {
- good = false;
- break;
- }
- xs.insert(x1);
- xs.insert(x2);
- }
- if (!good) {
- //assert(false);
- continue;
- }
- /*for (int i = 0; i < k; ++i) {
- int x = a * q[i].x + b * q[i].y;
- if (xs.find(x) != xs.end()) {
- good = false;
- break;
- }
- }*/
- if (good) {
- for (int i = 0; i < n; ++i) {
- int x = a * p[i].x + b * p[i].y;
- int y = c * p[i].x + d * p[i].y;
- p[i].x = x;
- p[i].y = y;
- }
- for (int i = 0; i < k; ++i) {
- int x = a * q[i].x + b * q[i].y;
- int y = c * q[i].x + d * q[i].y;
- q[i].x = x;
- q[i].y = y;
- }
- break;
- }
- //assert(false);
- }
- }
- void dfs(int v, int pe = -1) {
- used[v] = true;
- tin[v] = tout[v] = cur++;
- for (int i = 0; i < sz(neig[v]); ++i) {
- if (neig[v][i].sc == pe) {
- continue;
- }
- if (!used[neig[v][i].fs]) {
- dfs(neig[v][i].fs, neig[v][i].sc);
- tout[v] = min(tout[v], tout[neig[v][i].fs]);
- if (tout[neig[v][i].fs] > tin[v]) {
- is_bridge[neig[v][i].sc] = true;
- }
- } else {
- tout[v] = min(tout[v], tin[neig[v][i].fs]);
- }
- }
- }
- inline void del_bridge() {
- for (int i = 0; i < m; ++i) {
- neig[u[i]].pb(mp(v[i], i));
- neig[v[i]].pb(mp(u[i], i));
- }
- for (int i = 0; i < n; ++i) {
- if (!used[i]) {
- dfs(i);
- }
- }
- int nm = 0;
- for (int i = 0; i < m; ++i) {
- if (!is_bridge[i]) {
- u[nm] = u[i];
- v[nm++] = v[i];
- }
- }
- m = nm;
- }
- inline void calc(int v) {
- if (v == 0) {
- return;
- }
- d[v].p = 0;
- d[v].sum_bal = d[d[v].l].sum_bal + d[d[v].r].sum_bal + d[v].bal;
- if (d[v].l) {
- d[d[v].l].p = v;
- }
- if (d[v].r) {
- d[d[v].r].p = v;
- }
- }
- inline double get_y(const pair<point, point>& s, int x) {
- return s.fs.y + 1.0 * (s.sc.y - s.fs.y) * (x - s.fs.x) / (s.sc.x - s.fs.x);
- }
- inline bool cmp(int a, int b, int x) {
- if (x == segs[a].fs.x && x == segs[b].fs.x && segs[a].fs.y == segs[b].fs.y) {
- return vec(segs[a].sc - segs[a].fs, segs[b].sc - segs[a].fs) > 0;
- }
- if (x == segs[a].sc.x && x == segs[b].sc.x && segs[a].sc.y == segs[b].sc.y) {
- return vec(segs[a].sc - segs[a].fs, segs[b].sc - segs[a].fs) < 0;
- }
- return get_y(segs[a], x) < get_y(segs[b], x);
- }
- void split(int v, int num, int x, int &l, int &r) {
- if (v == 0) {
- l = r = 0;
- return;
- }
- if (cmp(d[v].num, num, x)) {
- split(d[v].r, num, x, d[v].r, r);
- l = v;
- } else {
- split(d[v].l, num, x, l, d[v].l);
- r = v;
- }
- calc(v);
- }
- int merge(int l, int r) {
- if (l == 0) {
- calc(r);
- return r;
- }
- if (r == 0) {
- calc(l);
- return l;
- }
- int res;
- if (d[l].h > d[r].h) {
- d[l].r = merge(d[l].r, r);
- res = l;
- } else {
- d[r].l = merge(l, d[r].l);
- res = r;
- }
- calc(res);
- return res;
- }
- inline node new_node(int num, int bal) {
- node res;
- res.num = num;
- res.bal = res.sum_bal = bal;
- res.p = res.l = res.r = 0;
- res.h = rand();
- return res;
- }
- inline void gen() {
- int n = int(1e5), m = int(1e5), q = int(1e5);
- cout << n << " " << m << " " << q << endl;
- for (int i = 0; i < n; ++i) {
- int x = 1e5 * cos(2 * pi / n * i);
- int y = 1e5 * sin(2 * pi / n * i);
- cout << x << " " << y << endl;
- }
- for (int i = 0; i < m; ++i) {
- cout << i + 1 << " " << (i + 1) % n + 1 << endl;
- }
- for (int i = 0; i < q; ++i) {
- cout << get_rand(-1e5, 1e5) << " " << get_rand(-1e5, 1e5) << endl;
- }
- exit(0);
- }
- int main() {
- //gen();
- #ifdef LOCAL42
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- cin >> n >> m >> k;
- for (int i = 0; i < n; ++i) {
- scanf("%d %d", &p[i].x, &p[i].y);
- }
- for (int i = 0; i < m; ++i) {
- scanf("%d %d", u + i, v + i);
- --u[i];
- --v[i];
- }
- for (int i = 0; i < k; ++i) {
- scanf("%d %d", &q[i].x, &q[i].y);
- }
- rotate();
- cerr << "ROTATE" << endl;
- del_bridge();
- for (int i = 0; i < m; ++i) {
- int a = u[i], b = v[i];
- g[a].pb(mp(p[b] - p[a], b));
- g[b].pb(mp(p[a] - p[b], a));
- }
- for (int i = 0; i < n; ++i) {
- sort(all(g[i]));
- for (int j = 0; j < sz(g[i]); ++j) {
- num[mp(i, g[i][j].sc)] = j;
- }
- }
- for (int i = 0; i < n; ++i) {
- for (int j = 0; j < sz(g[i]); ++j) {
- if (edges.find(mp(i, g[i][j].sc)) == edges.end()) {
- int a = i, b = g[i][j].sc;
- edges.insert(mp(a, b));
- lst.clear();
- lst.pb(mp(a, b));
- for (;;) {
- int pos = (num[mp(b, a)] - 1 + sz(g[b])) % sz(g[b]);
- int c = g[b][pos].sc;
- a = b;
- b = c;
- if (edges.find(mp(a, b)) != edges.end()) {
- break;
- }
- edges.insert(mp(a, b));
- lst.pb(mp(a, b));
- }
- ll s = 0;
- for (int z = 0; z < sz(lst); ++z) {
- s += vec(p[lst[z].fs], p[lst[z].sc]);
- }
- if (s >= 0) {
- continue;
- }
- for (int z = 0; z < sz(lst); ++z) {
- point a = p[lst[z].fs], b = p[lst[z].sc];
- int bal = -42;
- if (a.x > b.x) {
- bal = 1;
- } else {
- bal = -1;
- }
- if (a.x > b.x) {
- swap(a, b);
- }
- segs.pb(mp(a, b));
- events.pb(event(a.x, ADD, sz(segs) - 1, bal));
- events.pb(event(b.x, DEL, sz(segs) - 1, bal));
- }
- }
- }
- }
- for (int i = 0; i < k; ++i) {
- events.pb(event(q[i].x, QUERY, i, -42));
- }
- sort(all(events));
- int root = 0, sz = 0;
- for (int i = 0; i < sz(events); ++i) {
- if (events[i].t == ADD) {
- int l, r;
- split(root, events[i].num, events[i].x, l, r);
- d[++sz] = new_node(events[i].num, events[i].bal);
- node_num[events[i].num] = sz;
- root = merge(l, merge(sz, r));
- }
- if (events[i].t == DEL) {
- int v = node_num[events[i].num];
- int pv = d[v].p;
- if (pv == 0) {
- root = merge(d[v].l, d[v].r);
- } else {
- if (d[pv].r == v) {
- d[pv].r = merge(d[v].l, d[v].r);
- } else {
- d[pv].l = merge(d[v].l, d[v].r);
- }
- v = pv;
- while (v) {
- pv = d[v].p;
- calc(v);
- v = pv;
- }
- }
- }
- if (events[i].t == QUERY) {
- int j = events[i].num;
- segs.pb(mp(q[j], q[j] + point(1, 0)));
- int l, r;
- split(root, sz(segs) - 1, q[j].x, l, r);
- if (l > 0 && d[l].sum_bal > 0) {
- ans[j] = true;
- }
- root = merge(l, r);
- segs.pbk();
- }
- }
- for (int i = 0; i < k; ++i) {
- puts((ans[i] ? "Yes" : "No"));
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement