Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- typedef double T;
- const T INF = 1e100, EPS = 1e-6;
- struct PT {
- T x, y;
- PT() {}
- PT(T x, T y) : x(x), y(y) {}
- PT(const PT &p) : x(p.x), y(p.y) {}
- PT operator + (const PT &p) const {
- return PT(x+p.x, y+p.y);
- } PT operator - (const PT &p) const {
- return PT(x-p.x, y-p.y);
- } PT operator * (T c) const {
- return PT(x*c, y*c );
- } PT operator / (T c) const {
- return PT(x/c, y/c );
- } bool operator<(const PT &rhs) const {
- return make_pair(y,x)<make_pair(rhs.y,rhs.x);
- } bool operator==(const PT &rhs) const {
- return abs(y-rhs.y) < EPS and abs(x-rhs.x) < EPS;
- }
- };
- T dot(PT p, PT q) { return p.x*q.x+p.y*q.y; }
- T dist2(PT p, PT q) { return dot(p-q,p-q); }
- T cross(PT p,PT q){ return p.x*q.y-p.y*q.x; }
- ostream &operator<<(ostream &os, const PT &p) {
- return os << "(" << p.x << "," << p.y << ")";
- }
- PT RotateCCW90(PT p) { return PT(-p.y,p.x); }
- PT RotateCW90(PT p) { return PT(p.y,-p.x); }
- PT RotateCCW(PT p, T t) {
- return PT(p.x*cos(t)-p.y*sin(t),
- p.x*sin(t)+p.y*cos(t));
- } // rotate a point CCW or CW around the origin
- PT ProjectPointLine(PT a, PT b, PT c) {
- return a + (b-a)*dot(c-a, b-a)/dot(b-a, b-a);
- } // project point c onto line through a-b | a!=b
- PT ProjectPointSegment(PT a, PT b, PT c) {
- double r = dot(b-a,b-a);
- if(fabs(r) < EPS) return a;
- r = dot(c-a, b-a)/r;
- if(r < 0) return a;
- if(r > 1) return b;
- return a + (b-a)*r;
- } // project pt c onto segment through a & b
- bool LinesParallel(PT a, PT b, PT c, PT d) {
- return fabs(cross(b-a, c-d)) < EPS;
- } // line a-b, c-d parallel or collinear
- bool LinesCollinear(PT a, PT b, PT c, PT d) {
- return LinesParallel(a, b, c, d)
- && fabs(cross(a-b, a-c)) < EPS
- && fabs(cross(c-d, c-a)) < EPS;
- }
- bool SegmentsIntersect(PT a, PT b, PT c, PT d) {
- if(LinesCollinear(a, b, c, d)) {
- if(dist2(a, c) < EPS || dist2(a, d) < EPS ||
- dist2(b, c) < EPS || dist2(b, d) < EPS)
- return true;
- if(dot(c-a, c-b) > 0 && dot(d-a, d-b) > 0 &&
- dot(c-b, d-b) > 0) return false;
- return true;
- }
- if(cross(d-a, b-a) * cross(c-a, b-a) > EPS)
- return false;
- if(cross(a-c, d-c) * cross(b-c, d-c) > EPS)
- return false;
- return true;
- } // segment a-b intersect with c-d
- // Extreme Point for a direction is the farthest
- // point in that dir| poly is convex, CCW, no
- // redundant points| u direction for extremeness
- int extremePoint(const vector<PT> &poly, PT u=PT(0, 1)) {
- int n = (int) poly.size(); int a = 0, b = n;
- while(b - a > 1) {
- int c = (a + b) / 2;
- if(dot(poly[c] - poly[(c+1)%n], u) > 0 and dot(poly[c] - poly[(c-1+n)%n], u) > 0)
- return c;
- T a_dot = dot(poly[(a+1)%n] - poly[a], u);
- T c_dot = dot(poly[(c+1)%n] - poly[c], u);
- // bool a_zer = fabs(a_dot) < EPS;
- // bool c_zer = fabs(c_dot) < EPS;
- bool a_up = !(a_dot < 0);
- bool c_up = !(c_dot < 0);
- bool a_above_c = dot(poly[a]-poly[c], u) > 0;
- // if(a_zer or c_zer) {
- // if(a_zer and c_zer) {
- // if(a_above_c) return a;
- // else return c;
- // }
- // else if(a_zer) {
- // if(c_up) a = c;
- // else b = c;
- // }
- // else {
- // if(a_up) b = c;
- // else a = c;
- // }
- // continue;
- // }
- if(a_up and !c_up) b = c;
- else if(!a_up and c_up) a = c;
- else if(a_up and c_up) {
- if(a_above_c) b = c;
- else a = c;
- }
- else {
- if(!a_above_c) b = c;
- else a = c;
- }
- }
- if(dot(poly[a] - poly[(a+1)%n], u) > 0 and
- dot(poly[a]-poly[(a-1+n)%n], u) > 0) return a;
- return b % n;
- }
- inline bool OnSegment(PT a, PT b, PT c) {
- return abs(sqrtl(dist2(ProjectPointSegment(a, b, c), c))) < EPS;
- }
- inline bool SegmentsIntersex(PT a, PT b, PT c, PT d) {
- return OnSegment(a, b, c) or OnSegment(a, b, d) or OnSegment(c, d, a) or OnSegment(c, d, b);
- }
- bool ConvexPolygonIntersect(const vector<PT> &p, const vector<PT> &q) {
- int np = (int) p.size(), nq = (int) q.size();
- if(!np or !nq) return false;
- if(np == 1 and nq == 1) return p.front() == q.front();
- if(np == 1 and nq == 2) return (dist2(p.front(), ProjectPointSegment(q.front(), q.back(), p.front())) < EPS);
- if(np == 2 and nq == 1) return (dist2(q.front(), ProjectPointSegment(p.front(), p.back(), q.front())) < EPS);
- if(np == 2 and nq == 2) return SegmentsIntersect(p.front(), p.back(), q.front(), q.back());
- if(np > 1) for(int i=0; i<np; ++i) {
- PT a = p[i], b = p[(i+1) % np];
- // cerr << "P Side: " << a << " - " << b << "\n";
- PT dir = b - a;
- PT l_dir = RotateCCW90(dir), r_dir = RotateCW90(dir);
- PT plext = p[extremePoint(p, l_dir)];
- PT prext = p[extremePoint(p, r_dir)];
- PT qlext = q[extremePoint(q, l_dir)];
- PT qrext = q[extremePoint(q, r_dir)];
- // cerr << "Left extreme in dir " << l_dir << ": " << plext << " " << qlext << "\n";
- // cerr << "Rite extreme in dir " << r_dir << ": " << prext << " " << qrext << "\n";
- PT sa = a, sb = a + l_dir * 1;
- PT pl = ProjectPointLine(sa, sb, plext);
- PT pr = ProjectPointLine(sa, sb, prext);
- PT ql = ProjectPointLine(sa, sb, qlext);
- PT qr = ProjectPointLine(sa, sb, qrext);
- // cerr << pl << " - " << pr << " | " << ql << " - " << qr << "\n";
- // cerr << "SegmentIntersect: " << SegmentsIntersex(pl, pr, ql, qr) << "\n\n";
- if(!SegmentsIntersex(pl, pr, ql, qr)) return false;
- }
- if(nq > 1) for(int i=0; i<nq; ++i) {
- PT a = q[i], b = q[(i+1) % nq];
- // cerr << "Q Side: " << a << " - " << b << "\n";
- PT dir = b - a;
- PT l_dir = RotateCCW90(dir), r_dir = RotateCW90(dir);
- PT plext = p[extremePoint(p, l_dir)];
- PT prext = p[extremePoint(p, r_dir)];
- PT qlext = q[extremePoint(q, l_dir)];
- PT qrext = q[extremePoint(q, r_dir)];
- // cerr << "Left extreme in dir " << l_dir << ": " << plext << " " << qlext << "\n";
- // cerr << "Rite extreme in dir " << r_dir << ": " << prext << " " << qrext << "\n";
- PT sa = a, sb = a + l_dir * 1;
- PT pl = ProjectPointLine(sa, sb, plext);
- PT pr = ProjectPointLine(sa, sb, prext);
- PT ql = ProjectPointLine(sa, sb, qlext);
- PT qr = ProjectPointLine(sa, sb, qrext);
- // cerr << pl << " - " << pr << " | " << ql << " - " << qr << "\n";
- // cerr << "SegmentIntersect: " << SegmentsIntersex(pl, pr, ql, qr) << "\n\n";
- if(!SegmentsIntersex(pl, pr, ql, qr)) return false;
- }
- return true;
- }
- #define REMOVE_REDUNDANT
- T area2(PT a, PT b, PT c) {
- return cross(a,b) + cross(b,c) + cross(c,a);
- }
- #ifdef REMOVE_REDUNDANT
- bool between(const PT &a,const PT &b,const PT &c){
- return (fabs(area2(a,b,c)) < EPS && (a.x-b.x)*
- (c.x-b.x) <= 0 && (a.y-b.y)*(c.y-b.y) <= 0);
- }
- #endif
- void ConvexHull(vector<PT> &pts) {
- sort(pts.begin(), pts.end());
- pts.erase(unique(pts.begin(), pts.end()),
- pts.end());
- vector<PT> up, dn;
- for (int i = 0; i < pts.size(); i++) {
- while (up.size() > 1 && area2(up[up.size()-2],
- up.back(), pts[i]) >= 0) up.pop_back();
- while (dn.size() > 1 && area2(dn[dn.size()-2],
- dn.back(), pts[i]) <= 0) dn.pop_back();
- up.push_back(pts[i]); dn.push_back(pts[i]);
- }
- pts = dn;
- for (int i = (int) up.size() - 2; i >= 1; i--)
- pts.push_back(up[i]);
- #ifdef REMOVE_REDUNDANT
- if (pts.size() <= 2) return;
- dn.clear();
- dn.push_back(pts[0]);
- dn.push_back(pts[1]);
- for (int i = 2; i < pts.size(); i++) {
- if (between(dn[dn.size()-2], dn[dn.size()-1],
- pts[i])) dn.pop_back();
- dn.push_back(pts[i]);
- }
- if (dn.size() >= 3 &&
- between(dn.back(), dn[0], dn[1])) {
- dn[0] = dn.back(); dn.pop_back();
- }
- pts = dn;
- #endif
- }
- const int N = 1e5 + 7;
- typedef struct { int x, y, l; } dat;
- dat a[N];
- inline bool ok(int k) {
- vector<PT> p, q;
- for(int i=0; i<k; ++i) {
- if(a[i].l) p.push_back(PT(a[i].x, a[i].y));
- else q.push_back(PT(a[i].x, a[i].y));
- }
- ConvexHull(p);
- ConvexHull(q);
- return !ConvexPolygonIntersect(p, q);
- }
- int main() {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- int t, tc = 0;
- cin >> t;
- while(t--) {
- int n;
- cin >> n;
- for(int i=0; i<n; ++i) cin >> a[i].x >> a[i].y >> a[i].l;
- int lo = 0, hi = n;
- while(lo < hi) {
- int mid = (lo + hi + 1) / 2;
- if(ok(mid)) lo = mid;
- else hi = mid - 1;
- }
- cout << "Case " << ++tc << ":\n";
- for(int i=0; i<lo; ++i) cout << "YES\n";
- for(int i=lo; i<n; ++i) cout << "NO\n";
- }
- return 0;
- }
- void test() {
- // vector<PT> p = { {1, 2}, {2, 0}, {5, 0}, {7, 3}, {5, 5}, {2, 4} };
- // for(int i=0; i<(int) p.size(); ++i) {
- // PT a = p[i], b = p[(i+1) % (int) p.size()];
- // cerr << "Side: " << a << " - " << b << "\n";
- // PT dir = b - a;
- // PT l_dir = RotateCCW90(dir);
- // PT l_ext = p[extremePoint(p, l_dir)];
- // cerr << "Left extreme in dir " << l_dir << ": " << l_ext << "\n";
- // PT r_dir = RotateCW90(dir);
- // PT r_ext = p[extremePoint(p, r_dir)];
- // cerr << "Right extreme in dir " << r_dir << ": " << r_ext << "\n";
- // cerr << "\n";
- // }
- // vector<PT> p = { {1, 2}, {2, 0}, {5, 0}, {7, 3}, {5, 5}, {2, 4} };
- // vector<PT> q = { {8, -4}, {9, 1}, {10, 4}, {7, 6} };
- // vector<PT> q = { {3, 1}, {5, 1}, {6, 3}, {4, 4}, {3, 3} };
- // vector<PT> q = { {1, 4}, {1, 2.000001} };
- // vector<PT> q = { {1, 1.995} };
- // cerr << "Convex Polygon Intersect: " << boolalpha << ConvexPolygonIntersect(p, q) << "\n";
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement