Problem p00826 (C++) — buggy submission, verdict: Memory Limit Exceeded

/*
13:20 - 15:39 :: first time
15:39 -
 */

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a, b) (fabs((a) - (b)) < EPS)
#define MAX_N 5000
#define MAX_E 5000

using namespace std;

// Library - template - begin

class Point {

public:
  double x, y;

  Point(double x = -IINF, double y = -IINF) : x(x), y(y) {}

  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double a) { return Point(x * a, y * a); }
  Point operator/(double a) { return Point(x / a, y / a); }
  Point operator*(Point a) {
    return Point(x * a.x - y * a.y, x * a.y + y * a.x);
  }

  bool operator<(const Point &p) const {
    return !equals(x, p.x) ? x < p.x : y < p.y;
  }
  bool operator==(const Point &p) const {
    return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  }
};

struct Segment {
  Point p1, p2;
  Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
  bool operator==(const Segment &p) const { return p.p1 == p1 && p.p2 == p2; }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream &operator<<(ostream &os, const Point &a) {
  os << "(" << setw(3) << a.x << "," << setw(3) << a.y << ")";
}

ostream &operator<<(ostream &os, const Segment &a) {
  os << "( " << setw(5) << a.p1 << " , " << setw(5) << a.p2 << " )";
}

double dot(Point a, Point b) { return a.x * b.x + a.y * b.y; }
double cross(Point a, Point b) { return a.x * b.y - a.y * b.x; }
double norm(Point a) { return a.x * a.x + a.y * a.y; }
double abs(Point a) { return sqrt(norm(a)); }
Point rotate(Point a, double rad) {
  return Point(cos(rad) * a.x - sin(rad) * a.y,
               sin(rad) * a.x + cos(rad) * a.y);
}
double toRad(double agl) { return agl * M_PI / 180.0; }

// Library - template - end 13:32

// Library - CCW - begin

int ccw(Point p0, Point p1, Point p2) {
  Point a = p1 - p0;
  Point b = p2 - p0;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}

// Library - CCW - end 13:34

// Library - intersect - begin

bool intersectSS(Line s, Line t) {
  return ccw(s.p1, s.p2, t.p1) * ccw(s.p1, s.p2, t.p2) <= 0 &&
         ccw(t.p1, t.p2, s.p1) * ccw(t.p1, t.p2, s.p2) <= 0;
}

bool intersectSP(Line s, Point p) {
  return abs(s.p1 - p) + abs(s.p2 - p) - abs(s.p2 - s.p1) < EPS;
}

Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) {
    vector<Point> vec;
    vec.push_back(l.p1), vec.push_back(l.p2), vec.push_back(m.p1),
        vec.push_back(m.p2);
    sort(vec.begin(), vec.end());
    assert(vec[1] == vec[2]);
    return vec[1];
    // return m.p1;
  }
  if (abs(A) < EPS)
    assert(false);
  return m.p1 + (m.p2 - m.p1) * (B / A);
}

// Library - intersect - end 13:47

// Library - segmentArrangement - begin

struct Edge {
  int from, to, rev;
  double cost;
  Edge(int from = IINF, int to = IINF, int rev = IINF, double cost = IINF)
      : from(from), to(to), rev(rev), cost(cost) {}
  bool operator<(const Edge &a) const { return cost < a.cost; }
};

vector<vector<Edge>> segmentArrangement(vector<Segment> vs, vector<Point> &ps) {

  rep(i, vs.size()) REP(j, i + 1, vs.size()) if (intersectSS(vs[i], vs[j])) {
    // cout << vs[i] << " x " << vs[j] << " = "  << crosspoint(vs[i],vs[j]) <<
    // endl;
    ps.push_back(Point(crosspoint(vs[i], vs[j])));
  }

  sort(ps.begin(), ps.end());

  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  vector<vector<Edge>> ret(ps.size());

  for (int i = 0; i < vs.size(); i++) {
    vector<pair<double, int>> list;
    rep(j, ps.size()) if (intersectSP(vs[i], ps[j])) {
      list.push_back(pair<double, int>(norm(vs[i].p1 - ps[j]), j));
    }
    sort(list.begin(), list.end());
    for (int j = 0; j + 1 < list.size(); ++j) {
      int from = list[j].second, to = list[j + 1].second;
      double cost = abs(ps[from] - ps[to]);
      ret[from].push_back(Edge(from, to, ret[to].size(), cost));
      ret[to].push_back(Edge(to, from, ret[from].size() - 1, cost));
    }
  }
  return ret;
}

// Library - segmentArrangement - end 13:42

// Library - all - 27

// Library - add 15:29 -> 15:39

// Library - inPolygon - begin

double cross3p(Point p, Point q, Point r) {
  return (r.x - q.x) * (p.y - q.y) - (r.y - q.y) * (p.x - q.x);
}

bool collinear(Point p, Point q, Point r) {
  return fabs(cross3p(p, q, r)) < EPS;
}

bool ccwtest(Point p, Point q, Point r) { return cross3p(p, p, r) > 0; }

bool onSegment(Point p, Point q, Point r) {
  return collinear(p, q, r) &&
         equals(sqrt(pow(p.x - r.x, 2) + pow(p.y - r.y, 2)) +
                    sqrt(pow(r.x - q.x, 2) + pow(r.y - q.y, 2)),
                sqrt(pow(p.x - q.x, 2) + pow(p.y - q.y, 2)));
}

double angle(Point a, Point b, Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux * vx + uy * vy) /
              sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)));
}

bool inPolygon(Polygon poly, Point p) {
  if ((int)poly.size() == 0)
    return false;
  rep(i, poly.size()) if (onSegment(poly[i], poly[(i + 1) % (int)poly.size()],
                                    p)) return true;
  double sum = 0;
  rep(i, (int)poly.size()) {
    if (cross3p(p, poly[i], poly[(i + 1) % (int)poly.size()]) < 0)
      sum -= angle(p, poly[i], poly[(i + 1) % (int)poly.size()]);
    else
      sum += angle(p, poly[i], poly[(i + 1) % (int)poly.size()]);
  }
  return (fabs(sum - 2 * M_PI) < EPS || fabs(sum + 2 * M_PI) < EPS);
}

// Library - inPolygon - end 15:39

int n;
vector<Segment> segs;
vector<vector<Edge>> G;
vector<Point> ps;
bool used[MAX_N][MAX_E][2];
// used[ノード番号i][iのエッジj][方向k] := ノードiのエッジjの方向kを使ったか？
//  k->false : 出て行く方向　
//  k->true  : 入ってくる方向

bool cmp(const Edge &e1, const Edge &e2) {
  Point from = ps[e1.from];
  assert(e1.from == e2.from);
  Point to1 = ps[e1.to];
  Point to2 = ps[e2.to];
  double rad1 = atan2(to1.y - from.y, to1.x - from.x);
  double rad2 = atan2(to2.y - from.y, to2.x - from.x);
  return rad1 <= rad2;
}

// node => 今いるノード、 edge => 今いるノードから出る辺で、次に進む先を示す
void getCycle(int node, int edge, vector<Point> &cycle) {
  if (used[node][edge][false])
    return;

  int from = G[node][edge].from;
  int to = G[node][edge].to;
  int rev = G[node][edge].rev;
  cycle.push_back(ps[to]);
  assert(!used[node][edge][false] && !used[to][rev][true]);
  used[node][edge][false] = used[to][rev][true] = true;

  int next = (rev + 1) % (int)G[to].size();
  // cout << "(" << from << "=>" << to << " next = " << G[to][next].to << ")" <<
  // endl;
  getCycle(to, next, cycle);
}

void compute() {

  ps.clear();
  G.clear();
  G = segmentArrangement(segs, ps);

  int limit_e = 0;

  rep(i, G.size()) {
    sort(G[i].begin(), G[i].end(), cmp);
    limit_e = max(limit_e, (int)G[i].size());
  }

  rep(i, G.size()) {
    rep(j, G[i].size()) {
      int to = G[i][j].to;
      rep(k, G[to].size()) {
        if (G[i][j].from == G[to][k].to && G[i][j].to == G[to][k].from) {
          G[i][j].rev = k;
          G[to][k].rev = j;
        }
      }
    }
  }
  /*
  cout << "ps.size() = " << ps.size() << endl;
  rep(i,ps.size()){
  cout << "ps[" << i << "] = " << ps[i] << endl;
  }
  cout << "G---" << endl;
  rep(i,G.size()){
    for(Edge e : G[i]){
      cout << "(" << e.from << "->" << e.to << ", rev = " << e.rev << ", cost =
  " << e.cost << ") " << endl;
    }
    cout << endl;
  }
  cout << "====" << endl;
  */

  rep(i, G.size()) rep(j, limit_e) rep(k, 2) used[i][j][k] = false;

  rep(node, G.size()) {
    if (G[node].empty())
      continue;
    int from = G[node][0].from;
    assert(from == G[node][0].from);

    rep(edge, G[node].size()) {
      int to = G[node][edge].to;
      rep(dir, 2) {
        if (used[node][edge][dir])
          continue;
        vector<Point> cycle;
        int start_node, start_edge;
        if (dir == false) {
          cycle.push_back(ps[from]);
          start_node = from, start_edge = edge;
        } else {
          cycle.push_back(ps[to]);
          start_node = to, start_edge = G[node][edge].rev;
        }

        // cout << "cycle-search " << from << " to " << to << endl;
        getCycle(start_node, start_edge, cycle);
        int pos = IINF;
        rep(i, ps.size()) {
          if (ps[i] == cycle[cycle.size() - 1]) {
            pos = i;
            break;
          }
        }

        assert(cycle.size() >= 3);
        /*
        cout << "cycle - found" << endl;
        rep(i,cycle.size()){
          cout << cycle[i] << " ";
        }cout << endl << endl;
        */
        if (inPolygon(cycle, Point(0, 0))) {
          cout << "yes" << endl;
          return;
        }
      }
    }
  }

  cout << "no" << endl;
}

int main() {

  while (cin >> n, n) {
    segs.clear();
    segs.resize(n);

    for (Segment &seg : segs)
      cin >> seg.p1.x >> seg.p1.y >> seg.p2.x >> seg.p2.y;

    compute();
  }

  return 0;
}

/*
  bool art = false;
  rep(i,G[start_node].size()){
  if(G[start_node][i].from == start_node &&
  G[start_node][i].to   == from){
  start_edge = i;
  art= true;
  }
  }
  assert(art);
*/

Error: MLE

Fixed submission:

/*
13:20 - 15:39 :: first time
15:39 -
 */

#include <algorithm>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define IINF (INT_MAX)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a, b) (fabs((a) - (b)) < EPS)
#define MAX_N 5000
#define MAX_E 7000

using namespace std;

// Library - template - begin

class Point {

public:
  double x, y;

  Point(double x = -IINF, double y = -IINF) : x(x), y(y) {}

  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double a) { return Point(x * a, y * a); }
  Point operator/(double a) { return Point(x / a, y / a); }
  Point operator*(Point a) {
    return Point(x * a.x - y * a.y, x * a.y + y * a.x);
  }

  bool operator<(const Point &p) const {
    return !equals(x, p.x) ? x < p.x : y < p.y;
  }
  bool operator==(const Point &p) const {
    return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
  }
};

struct Segment {
  Point p1, p2;
  Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
  bool operator==(const Segment &p) const { return p.p1 == p1 && p.p2 == p2; }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream &operator<<(ostream &os, const Point &a) {
  os << "(" << a.x << "," << a.y << ")";
}

ostream &operator<<(ostream &os, const Segment &a) {
  os << "( " << a.p1 << " , " << a.p2 << " )";
}

double dot(Point a, Point b) { return a.x * b.x + a.y * b.y; }
double cross(Point a, Point b) { return a.x * b.y - a.y * b.x; }
double norm(Point a) { return a.x * a.x + a.y * a.y; }
double abs(Point a) { return sqrt(norm(a)); }
Point rotate(Point a, double rad) {
  return Point(cos(rad) * a.x - sin(rad) * a.y,
               sin(rad) * a.x + cos(rad) * a.y);
}
double toRad(double agl) { return agl * M_PI / 180.0; }

// Library - template - end 13:32

// Library - CCW - begin

int ccw(Point p0, Point p1, Point p2) {
  Point a = p1 - p0;
  Point b = p2 - p0;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) < norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}

// Library - CCW - end 13:34

// Library - intersect - begin

bool intersectSS(Line s, Line t) {
  return ccw(s.p1, s.p2, t.p1) * ccw(s.p1, s.p2, t.p2) <= 0 &&
         ccw(t.p1, t.p2, s.p1) * ccw(t.p1, t.p2, s.p2) <= 0;
}

bool intersectSP(Line s, Point p) {
  return abs(s.p1 - p) + abs(s.p2 - p) - abs(s.p2 - s.p1) < EPS;
}

Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS)
    return m.p1;
  if (abs(A) < EPS)
    assert(false);
  return m.p1 + (m.p2 - m.p1) * (B / A);
}

// Library - intersect - end 13:47

// Library - segmentArrangement - begin

struct Edge {
  int from, to, rev;
  double cost;
  Edge(int from = IINF, int to = IINF, int rev = IINF, double cost = IINF)
      : from(from), to(to), rev(rev), cost(cost) {}
  bool operator<(const Edge &a) const { return cost < a.cost; }
};

vector<vector<Edge>> segmentArrangement(vector<Segment> vs, vector<Point> &ps) {

  rep(i, vs.size()) REP(j, i + 1, vs.size()) if (intersectSS(vs[i], vs[j])) {
    ps.push_back(Point(crosspoint(vs[i], vs[j])));
  }

  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  vector<vector<Edge>> ret(ps.size());

  for (int i = 0; i < vs.size(); i++) {
    vector<pair<double, int>> list;
    rep(j, ps.size()) if (intersectSP(vs[i], ps[j])) {
      list.push_back(pair<double, int>(norm(vs[i].p1 - ps[j]), j));
    }
    sort(list.begin(), list.end());
    for (int j = 0; j + 1 < list.size(); ++j) {
      int from = list[j].second, to = list[j + 1].second;
      double cost = abs(ps[from] - ps[to]);
      ret[from].push_back(Edge(from, to, ret[to].size(), cost));
      ret[to].push_back(Edge(to, from, ret[from].size() - 1, cost));
    }
  }
  return ret;
}

// Library - segmentArrangement - end 13:42

// Library - all - 27

// Library - add 15:29 -> 15:39

// Library - inPolygon - begin

double cross3p(Point p, Point q, Point r) {
  return (r.x - q.x) * (p.y - q.y) - (r.y - q.y) * (p.x - q.x);
}

bool collinear(Point p, Point q, Point r) {
  return fabs(cross3p(p, q, r)) < EPS;
}

bool ccwtest(Point p, Point q, Point r) { return cross3p(p, p, r) > 0; }

bool onSegment(Point p, Point q, Point r) {
  return collinear(p, q, r) &&
         equals(sqrt(pow(p.x - r.x, 2) + pow(p.y - r.y, 2)) +
                    sqrt(pow(r.x - q.x, 2) + pow(r.y - q.y, 2)),
                sqrt(pow(p.x - q.x, 2) + pow(p.y - q.y, 2)));
}

double angle(Point a, Point b, Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux * vx + uy * vy) /
              sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)));
}

bool inPolygon(Polygon poly, Point p) {
  if ((int)poly.size() == 0)
    return false;
  rep(i, poly.size()) if (onSegment(poly[i], poly[(i + 1) % (int)poly.size()],
                                    p)) return true;
  double sum = 0;
  rep(i, (int)poly.size()) {
    if (cross3p(p, poly[i], poly[(i + 1) % (int)poly.size()]) < 0)
      sum -= angle(p, poly[i], poly[(i + 1) % (int)poly.size()]);
    else
      sum += angle(p, poly[i], poly[(i + 1) % (int)poly.size()]);
  }
  return (fabs(sum - 2 * M_PI) < EPS || fabs(sum + 2 * M_PI) < EPS);
}

// Library - inPolygon - end 15:39

int n;
vector<Segment> segs;
vector<vector<Edge>> G;
vector<Point> ps;
bool used[MAX_N][MAX_E][2];
// used[ノード番号i][iのエッジj][方向k] := ノードiのエッジjの方向kを使ったか？
//  k->false : 出て行く方向　
//  k->true  : 入ってくる方向

bool cmp(const Edge &e1, const Edge &e2) {
  Point from = ps[e1.from];
  assert(e1.from == e2.from);
  Point to1 = ps[e1.to];
  Point to2 = ps[e2.to];
  double rad1 = atan2(to1.y - from.y, to1.x - from.x);
  double rad2 = atan2(to2.y - from.y, to2.x - from.x);
  return rad1 <= rad2;
}

// node => 今いるノード、 edge => 今いるノードから出る辺で、次に進む先を示す
void getCycle(int node, int edge, vector<Point> &cycle) {
  if (used[node][edge][false])
    return;

  int from = G[node][edge].from;
  int to = G[node][edge].to;
  int rev = G[node][edge].rev;
  cycle.push_back(ps[to]);
  assert(!used[node][edge][false] && !used[to][rev][true]);
  used[node][edge][false] = used[to][rev][true] = true;

  int next = (rev + 1) % (int)G[to].size();
  // cout << "(" << from << "=>" << to << " next = " << G[to][next].to << ")" <<
  // endl;
  getCycle(to, next, cycle);
}

void compute() {

  ps.clear();
  G.clear();
  G = segmentArrangement(segs, ps);

  int limit_e = 0;

  // cout << "ps.size() = " << ps.size() << endl;
  // rep(i,ps.size()){
  // cout << "ps[" << i << "] = " << ps[i] << endl;
  // }
  rep(i, G.size()) {
    sort(G[i].begin(), G[i].end(), cmp);
    limit_e = max(limit_e, (int)G[i].size());
  }

  rep(i, G.size()) {
    rep(j, G[i].size()) {
      int to = G[i][j].to;
      rep(k, G[to].size()) {
        if (G[i][j].from == G[to][k].to && G[i][j].to == G[to][k].from) {
          G[i][j].rev = k;
          G[to][k].rev = j;
        }
      }
    }
  }
  /*
  cout << "G---" << endl;
  rep(i,G.size()){
    for(Edge e : G[i]){
      cout << "(" << e.from << "->" << e.to << ", rev = " << e.rev << ", cost =
  " << e.cost << ") " << endl;
    }
    cout << endl;
  }
  cout << "====" << endl;
  */

  rep(i, G.size()) rep(j, limit_e) rep(k, 2) used[i][j][k] = false;

  rep(node, G.size()) {
    if (G[node].empty())
      continue;
    int from = G[node][0].from;
    assert(from == G[node][0].from);

    rep(edge, G[node].size()) {
      int to = G[node][edge].to;
      rep(dir, 2) {
        if (used[node][edge][dir])
          continue;
        vector<Point> cycle;
        int start_node, start_edge;
        if (dir == false) {
          cycle.push_back(ps[from]);
          start_node = from, start_edge = edge;
        } else {
          cycle.push_back(ps[to]);
          start_node = to, start_edge = G[node][edge].rev;
        }

        // cout << "cycle-search " << from << " to " << to << endl;
        getCycle(start_node, start_edge, cycle);
        int pos = IINF;
        rep(i, ps.size()) {
          if (ps[i] == cycle[cycle.size() - 1]) {
            pos = i;
            break;
          }
        }
        /*
        bool check = false;
        rep(){

        }
        if(!check)continue;
        */
        assert(cycle.size() >= 3);
        /*
        cout << "cycle - found" << endl;
        rep(i,cycle.size()){
          cout << cycle[i] << " ";
        }cout << endl << endl;
        */
        if (inPolygon(cycle, Point(0, 0))) {
          cout << "yes" << endl;
          return;
        }
      }
    }
  }

  cout << "no" << endl;
}

int main() {

  while (cin >> n, n) {
    segs.clear();
    segs.resize(n);

    for (Segment &seg : segs)
      cin >> seg.p1.x >> seg.p1.y >> seg.p2.x >> seg.p2.y;

    compute();
  }

  return 0;
}

/*
  bool art = false;
  rep(i,G[start_node].size()){
  if(G[start_node][i].from == start_node &&
  G[start_node][i].to   == from){
  start_edge = i;
  art= true;
  }
  }
  assert(art);
*/