WA on 23... Ural 1469

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;
}

 

写得巨丑, 有空重写一发吧.

posted @ 2017-12-11 20:09  ichneumon  阅读(268)  评论(0编辑  收藏  举报