http://acm.timus.ru/problem.aspx?space=1&num=1469
#include <assert.h> #include <set> #include <algorithm> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int N = 5e4 + 100; const double EPS = 1e-5; int sgn(double x) { return x < -EPS ? -1 : EPS < x; } typedef double db; struct Poi { db x, y; Poi() {} Poi(db x, db y):x(x), y(y) {} bool operator < (const Poi&rhs) const { return sgn(x - rhs.x) < 0 || (sgn(x - rhs.x) == 0 && sgn(y - rhs.y) < 0); } bool operator == (const Poi&rhs) const{ return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0; } }; Poi operator - (Poi a, Poi b) { return Poi(a.x - b.x, a.y - b.y); } struct Seg { Poi a, b; void read() { scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y); if (b < a) swap(a, b); assert(!(a == b)); } } s[N]; db cross(const Poi&a, const Poi&b) { return a.x * b.y - a.y * b.x; } db dot(const Poi&a, const Poi&b) { return a.x * b.x + a.y * b.y; } bool onLeft(Seg s, Poi p) { return cross(p - s.a, s.b - s.a) > 0; } bool onSeg(Seg s, Poi p) { return sgn(cross(p - s.a, s.b - s.a)) == 0 && sgn(dot(p - s.a, s.b - s.a)) >= 0 && sgn(dot(p - s.b, s.a - s.b)) >= 0; } bool hasInter(int i, int j) { if (onSeg(s[i], s[j].a) || onSeg(s[i], s[j].b) || onSeg(s[j], s[i].a) || onSeg(s[j], s[i].b)) return true; int a, b; a = onLeft(s[i], s[j].a); b = onLeft(s[i], s[j].b); if (a == b) return false; a = onLeft(s[j], s[i].a); b = onLeft(s[j], s[i].b); if (a == b) return false; return true; } struct Event { int type; // 0 for left end, 1 for right end int segId; Poi *p; Event() {} Event(int type, int segId, Poi*p):type(type), segId(segId), p(p) {} bool operator < (const Event&rhs) const { return *p < *rhs.p || (*p == *rhs.p && type < rhs.type); } }; struct EventQueue:vector<Event> { int cur; Event* nextEvent() { if (cur < size()) return &at(cur++); return NULL; } } EQ; void end(int i, int j) { puts("YES"); printf("%d %d\n", i, j); exit(0); } struct TNode; typedef set<TNode>::iterator iter; struct TNode { int segId; TNode(int segId):segId(segId) {} bool operator < (const TNode&rhs) const { if (rhs.segId != segId && hasInter(rhs.segId, segId)) end(segId, rhs.segId); int t = sgn(cross(s[rhs.segId].a - s[segId].a, s[segId].b - s[segId].a)); return t < 0; } bool operator == (const TNode&rhs) const { return segId == rhs.segId; } }; iter pos[N]; struct SweepLine:set<TNode> { bool add(Event*e, int&i, int&j) { pos[e->segId] = insert(TNode(e->segId)).first; iter it = pos[e->segId]; iter pre = it, suf = it; --pre, ++suf; i = it->segId; if (pre != end()) { j = pre->segId; if (i != j && hasInter(i, j)) { return true; } } if (suf != end()) { j = suf->segId; if (i != j && hasInter(i, j)) { return true; } } return false; } bool del(Event*e, int &i, int&j) { iter it = pos[e->segId]; iter pre = it, suf = it; --pre, ++suf; if (pre != end() && suf != end()) { i = pre->segId, j = suf->segId; if (i != j && hasInter(i, j)) return true; } erase(it); return false; } } SL; int main() { #ifdef lol freopen("1469.in", "r", stdin); freopen("1469.out", "w", stdout); #endif int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) { s[i].read(); } for (int i = 1; i <= n; ++i) { EQ.push_back(Event(0, i, &s[i].a)); EQ.push_back(Event(1, i, &s[i].b)); } sort(EQ.begin(), EQ.end()); Event* e; int i, j; bool ok = false; while (!ok && (e = EQ.nextEvent()) != NULL) { // printf("%d %d\n", e->type, e->segId); if (e->type == 0) { if (SL.add(e, i, j)) ok = true; } else { if (SL.del(e, i, j)) ok = true; } } if (ok) { puts("YES"); printf("%d %d\n", i, j); } else { puts("NO"); } return 0; }
写得巨丑, 有空重写一发吧.