Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <cassert>
- #include <algorithm>
- #include <vector>
- #include <set>
- #include "testlib.h"
- using namespace std;
- typedef long long llong;
- const int N = 100000;
- const int Q = 500000;
- const int MAX = 200000000;
- int line[3 * N];
- struct vt
- {
- static const int VMAX = 1000000000;
- int x, y;
- vt(){}
- vt(int _x, int _y)
- {
- x = _x, y = _y;
- if (abs(x) > VMAX || abs(y) > VMAX)
- {
- fprintf(stderr, "Program is about to overflow in internal calculations, sorry =( change VMAX constant if you are sure what you're doing");
- throw 42;
- }
- }
- friend vt operator -(vt a, vt b)
- {
- return vt(a.x - b.x, a.y - b.y);
- }
- friend llong operator ^(vt a, vt b)
- {
- return (llong)a.x * b.y - (llong)b.x * a.y;
- }
- friend vt operator ~(vt a)
- {
- return vt(a.y, -a.x);
- }
- friend vt operator /(vt a, int k)
- {
- assert(a.x % k == 0 && a.y % k == 0);
- return vt(a.x / k, a.y / k);
- }
- char* to_string()
- {
- char* buf = new char[50];
- sprintf(buf, "(%d, %d)", x, y);
- return buf;
- }
- };
- struct CheckNonIntersection
- {
- typedef vector<pair<vt, vt> > SV;
- SV S;
- char sign(llong x)
- {
- return (x > 0) - (x < 0);
- }
- inline bool inter(vt a, vt b, vt c, vt d)
- {
- return (sign((b - a) ^ (c - a)) * sign((b - a) ^ (d - a))) + (sign((d - c) ^ (a - c)) * sign((d - c) ^ (b - c))) < 0;
- }
- inline llong gcd(llong a, llong b)
- {
- if (a < 0)
- a = -a;
- if (b < 0)
- b = -b;
- while (b)
- a %= b, swap(a, b);
- return a;
- }
- static inline bool cmp_lex(vt a, vt b)
- {
- return (a.x != b.x) ? a.x < b.x : a.y < b.y;
- }
- vt find_new_basis()
- {
- vector<vt> used;
- for (int i = 0; i < S.size(); i++)
- {
- vt v = S[i].second - S[i].first;
- llong g = gcd(v.x, v.y);
- assert(g != 0);
- v = v / g;
- for (int it = 0; it < 4; it++, v = ~v)
- if (v.x >= 0 && v.y >= 0)
- used.push_back(v);
- }
- sort(used.begin(), used.end(), cmp_lex);
- vt b;
- for (int s = 1; s <= 1000; s++)
- {
- for (int y = 0; y <= s; y++)
- {
- int x = s - y;
- if (gcd(x, y) != 1)
- continue;
- if (binary_search(used.begin(), used.end(), vt(y, x), cmp_lex))
- continue;
- return vt(x, y);
- }
- }
- assert(false);
- }
- vt apply_basis(vt v, vt b)
- {
- return vt(b.x * v.x - b.y * v.y, b.y * v.x + b.x * v.y);
- }
- struct cmp_by_x
- {
- vector<pair<vt, vt> >& S;
- cmp_by_x(vector<pair<vt, vt> > &_S) : S(_S) {}
- inline bool operator()(int a, int b)
- {
- int u = (a >= 0) ? S[a].first.x : S[~a].second.x;
- int v = (b >= 0) ? S[b].first.x : S[~b].second.x;
- if (u != v)
- return u < v;
- else
- return (a >= 0) < (b >= 0);
- }
- };
- struct cmp_by_y
- {
- int& x;
- vector<pair<vt, vt> >& S;
- cmp_by_y(int& _x, vector<pair<vt, vt> >& _S) : x(_x), S(_S)
- {
- for (int i = 0; i < S.size(); i++)
- assert(S[i].first.x < S[i].second.x);
- }
- inline bool operator ()(int i, int j)
- {
- llong iu = (llong)(S[i].second.x - x) * S[i].first.y + (llong)(x - S[i].first.x) * S[i].second.y;
- llong ju = (llong)(S[j].second.x - x) * S[j].first.y + (llong)(x - S[j].first.x) * S[j].second.y;
- int id = (S[i].second.x - S[i].first.x);
- int jd = (S[j].second.x - S[j].first.x);
- if (abs(iu / id - ju / jd) >= 2)
- return iu / id < ju / jd;
- else
- return iu * jd - ju * id < 0;
- }
- };
- inline void check_inter(int i, int j)
- {
- quitif(inter(S[i].first, S[i].second, S[j].first, S[j].second), _fail, "Segments from lines %d and %d are intersecting", line[i], line[j]);
- }
- CheckNonIntersection(vector<pair<vt, vt> > _S)
- {
- S = _S;
- vt u = find_new_basis();
- for (int i = 0; i < S.size(); i++)
- {
- S[i].first = apply_basis(S[i].first, u), S[i].second = apply_basis(S[i].second, u);
- if (S[i].first.x > S[i].second.x)
- swap(S[i].first, S[i].second);
- S[i].first.x *= 2, S[i].second.x *= 2;
- assert(S[i].first.x != S[i].second.x);
- }
- int x;
- multiset<int, cmp_by_y> A(cmp_by_y(x, S));
- vector<int> ev(2 * S.size());
- for (int i = 0; i < S.size(); i++)
- ev[2 * i] = i, ev[2 * i + 1] = ~i;
- sort(ev.begin(), ev.end(), cmp_by_x(S));
- vector<multiset<int, cmp_by_y>::iterator> pos(S.size(), A.end());
- for (int i = 0; i + 1 < ev.size(); i++)
- {
- int v = ev[i], w = ev[i + 1];
- int ax = (v >= 0) ? S[v].first.x : S[~v].second.x;
- int bx = (w >= 0) ? S[w].first.x : S[~w].second.y; // !!!!!!!!!!
- x = (ax + bx) / 2;
- if (v >= 0)
- {
- pos[v] = A.insert(v);
- multiset<int, cmp_by_y>::iterator it = pos[v];
- if (it != A.begin())
- check_inter(v, *(--it)), it = pos[v];
- if ((++it) != A.end())
- check_inter(v, *it);
- }
- else
- {
- multiset<int, cmp_by_y>::iterator itl = pos[~v], itr = pos[~v];
- if (itl != A.begin() && (++itr) != A.end())
- check_inter(*(--itl), *itr);
- A.erase(pos[~v]);
- pos[~v] = A.end();
- }
- }
- }
- };
- vector<int> E[3 * N];
- vt P[N];
- struct cmp_by_ang
- {
- vt O;
- cmp_by_ang(vt _O) { O = _O; }
- inline bool operator()(int a, int b)
- {
- vt u = P[a] - O, v = P[b] - O;
- int pu = (u.y > 0 || (u.x > 0 && u.y == 0));
- int pv = (v.y > 0 || (v.x > 0 && v.y == 0));
- if (pu != pv)
- return pu > pv;
- return (u ^ v) >= 0;
- }
- };
- bool was[N];
- void DFS(int x)
- {
- was[x] = true;
- for (int i = 0; i < E[x].size(); i++)
- {
- int y = E[x][i];
- if (!was[y])
- DFS(y);
- }
- }
- set<pair<int, int> > points;
- set<pair<int, int> > edges;
- int main()
- {
- registerValidation();
- int n, k;
- n = inf.readInt(1, N);
- inf.readEoln();
- for (int i = 0; i < n; i++)
- {
- int x = inf.readInt(-MAX, MAX);
- inf.readSpace();
- int y = inf.readInt(-MAX, MAX);
- inf.readEoln();
- P[i] = vt(x, y);
- quitif(!points.insert(make_pair(x, y)).second, _fail, "point %d: %d %d is already used", i, P[i].x, P[i].y);
- }
- k = inf.readInt(1, Q);
- inf.readEoln();
- vector<pair<vt, vt> > VE;
- for (int i = 0; i < k; i++)
- {
- int t = inf.readInt(0, 1);
- inf.readSpace();
- int a = inf.readInt(0, n - 1);
- inf.readSpace();
- int b = inf.readInt(0, n - 1);
- if (t == 1)
- {
- quitif(!edges.insert(make_pair(a, b)).second, _fail, "query %d: edge %d %d is already on the picture", i, a, b);
- quitif(!edges.insert(make_pair(b, a)).second, _fail, "query %d: edge %d %d is already on the picture", i, a, b);
- line[VE.size()] = i;
- VE.push_back(make_pair(P[a], P[b]));
- E[a].push_back(b);
- E[b].push_back(a);
- }
- else
- quitif(edges.find(make_pair(a, b)) == edges.end(), _fail, "query %d: edge %d %d isn't presented yet", i, a, b);
- quitif(a == b, _fail, "query %d: equal numbers in query", i);
- inf.readEoln();
- }
- inf.readEof();
- try
- {
- new CheckNonIntersection(VE);
- }
- catch (int e)
- {
- assert(e == 42);
- }
- for (int i = 0; i < n; i++)
- sort(E[i].begin(), E[i].end(), cmp_by_ang(P[i]));
- DFS(0);
- for (int i = 0; i < n; i++)
- quitif(!was[i], _fail, "point %d isn't connected with 0", i);
- for (int i = 0; i < n; i++)
- {
- for (int j = 0; j < E[i].size(); j++)
- {
- int u = E[i][j];
- int v = E[i][(j + 1) % E[i].size()];
- if (((P[u] - P[i]) ^ (P[v] - P[i])) <= 0)
- continue;
- quitif(edges.find(make_pair(u, v)) == edges.end(), _fail, "there are edges %d %d and %d %d but no edge %d %d", i, u, i, v, u, v);
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement