QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#331125#7693. Convex Hull Extensionlmf_upAC ✓3ms3992kbC++2032.2kb2024-02-18 01:32:432024-02-18 01:32:43

Judging History

你现在查看的是最新测评结果

  • [2024-02-18 01:32:43]
  • 评测
  • 测评结果:AC
  • 用时:3ms
  • 内存:3992kb
  • [2024-02-18 01:32:43]
  • 提交

answer

#include<bits/stdc++.h>

#define cp const point &
#define cl const line &
#define cc const circle &
#define LD long double
std::mt19937 rnd(time(0));
const LD eps = 1e-8;
const LD pi = std::numbers::pi;
const LD INF = 1e9;

int sgn(LD x)
{
    return x > eps ? 1 : (x < -eps ? -1 : 0);
}

LD sqr(LD x)
{ return x * x; }

struct point
{
    LD x, y;

    point operator+(cp a) const
    { return {x + a.x, y + a.y}; }

    point operator-(cp a) const
    { return {x - a.x, y - a.y}; }

    point operator*(LD t) const
    { return {x * t, y * t}; }

    point operator/(LD t) const
    { return {x / t, y / t}; }

    point rot(LD t) const
    { return {(LD) (x * cos(t) - y * sin(t)), (LD) (x * sin(t) + y * cos(t))}; }

    point rot90() const
    { return {-y, x}; }

    LD len2() const
    { return x * x + y * y; }

    LD len() const
    { return sqrtl(x * x + y * y); }

    point unit() const
    {
        LD d = len();
        return {(LD) (x / d), (LD) (y / d)};
    }

    int on_up()//b不判(0,0)
    {
        return sgn(y) == 1 || (sgn(y) == 0 && sgn(x) < 0);
    }

    void print()
    {
        std::cout << x << ' ' << y << std::endl;
    }

    void read()
    {
        int xx, yy;
        std::cin >> xx >> yy;
        x = xx, y = yy;
    }

    friend bool operator<(cp a, cp b)
    {
        return a.x == b.x ? a.y < b.y : a.x < b.x;
    }

    friend bool operator>(cp a, cp b)
    {
        return a.x == b.x ? a.y > b.y : a.x > b.x;
    }
};

LD dot(cp a, cp b);

bool operator==(cp a, cp b)
{
    return !sgn(dot(a - b, a - b));
//    return !sgn(a.x-b.x)&&!(a.y-b.y);看题目
}

LD dis(cp a, cp b)//两点距离
{
    return sqrtl(sqr(a.x - b.x) + sqr(a.y - b.y));
}

LD dot(cp a, cp b)//点乘
{
    return a.x * b.x + a.y * b.y;
}

LD det(cp a, cp b)//叉乘
{
    return a.x * b.y - b.x * a.y;
}

bool turn_left(cp a, cp b, cp c)//判断ba是否逆时针转少于180°到ca
{
    return sgn(det(b - a, c - a)) > 0;//大于是严格凸包
}

struct line
{
    point s, t;

    line()
    {}

    line(point a, point b) : s(a), t(b)
    {}

    void read()
    {
        s.read(), t.read();
    }

    void print()
    {
        s.print(), std::cout << ' ', t.print();
    }

};

struct circle
{
    point c;
    LD r;

    circle()
    {}

    circle(point C, LD R)
    { c = C, r = R; }
};

bool in_circle(cp a, cc b)
{
    return sgn((b.c - a).len() - b.r) <= 0;
}

circle make_circle(point u, point v)
{
    point p = (u + v) / 2;
    return circle(p, (u - p).len());
}

circle make_circle(cp a, cp b, cp c)
{
    point p = b - a, q = c - a;
    point s(dot(p, p) / 2, dot(q, q) / 2);
    LD d = det(p, q);
    p = point(det(s, point(p.y, q.y)), det(point(p.x, q.x), s)) / d;
    return circle(a + p, p.len());
}

circle min_circle(std::vector<point> p)
{
    circle ret(p[0], 0);
    std::shuffle(p.begin(), p.end(), rnd);
    int len = p.size();
    for (int i = 0; i < len; i++)
        if (!in_circle(p[i], ret))
        {
            ret = circle(p[i], 0);
            for (int j = 0; j < i; j++)
                if (!in_circle(p[j], ret))
                {
                    ret = make_circle(p[j], p[i]);
                    for (int k = 0; k < j; ++k)
                        if (!in_circle(p[k], ret))
                            ret = make_circle(p[i], p[j], p[k]);
                }
        }
    return ret;
}

LD get_rad(point a, point b)
{
    if (a == point(0, 0) || b == point(0, 0))
        return 0;
    else
    {
        return acosl(dot(a, b) / (a.len() * b.len()));
    }
}

bool same_dir(cl a, cl b)//判断方向是否一致
{
    return sgn(det(b.t - b.s, a.t - a.s)) == 0 && sgn(dot(b.t - b.s, a.t - a.s)) > 0;
}

bool point_on_line(cp a, cl l)//判断点是否在直线上
{
    return sgn(det(a - l.s, l.t - l.s)) == 0;
}

bool point_on_segment(cp a, cl l)//判断点是否在线段上
{
    return point_on_line(a, l) && sgn(dot(l.s - a, l.t - a)) <= 0;//(<=代表可以端点
}

bool two_side(cp a, cp b, cl c)//判断两个点是否在线段的两边
{
    return sgn(det(a - c.s, c.t - c.s)) * sgn(det(b - c.s, c.t - c.s)) < 0;
}

bool intersect_judge_strict(cl a, cl b)
{
    return two_side(a.s, a.t, b) && two_side(b.s, b.t, a);
}

bool intersect_judge(cl a, cl b)
{//判断两个线段是否相交
    if (point_on_segment(a.s, b) || point_on_segment(a.t, b) || point_on_segment(b.s, a) ||
        point_on_segment(b.t, a))
        return true;
    return intersect_judge_strict(a, b);
}


point line_intersect(cl a, cl b)
{//得到两线段的交点
    LD s1 = det(a.t - a.s, b.s - a.s);
    LD s2 = det(a.t - a.s, b.t - a.s);
    return (b.s * s2 - b.t * s1) / (s2 - s1);
}

bool point_on_ray(cp a, cl b)
{//判断点是否在射线上
    return sgn(det(a - b.s, b.t - b.s)) == 0 && sgn(dot(a - b.s, b.t - b.s)) >= 0;
}

bool ray_intersect_judge(line a, line b)//判断两射线是否相交
{
    LD s1, s2;
    s1 = det(a.t - a.s, b.s - a.s);
    s2 = det(a.t - a.s, b.t - a.s);
    if (sgn(s1) == 0 && sgn(s2) == 0)
        return sgn(dot(a.t - a.s, b.s - a.s)) >= 0 || sgn(dot(b.t - b.s, a.s - b.s));
    if (!sgn(s1 - s2) || sgn(s1) == sgn(s2 - s1))return 0;
    std::swap(a, b);
    s1 = det(a.t - a.s, b.s - a.s);
    s2 = det(a.t - a.s, b.t - a.s);
    return sgn(s1) != sgn(s2 - s1);
}

LD point_to_line(cp a, cl b)
{//点到直线的距离
    return abs(det(b.t - b.s, a - b.s)) / dis(b.s, b.t);
}

point project_to_line(cp a, cl b)
{//得到点在线上的投影
    return b.s + (b.t - b.s) * (dot(a - b.s, b.t - b.s) / (b.t - b.s).len2());
}

LD point_to_segment(cp a, cl b)
{//点到线段的距离
    if (b.s == b.t)
        return dis(a, b.s);
    if (sgn(dot(b.s - a, b.t - b.s)) * sgn(dot(b.t - a, b.t - b.s)) <= 0)
        return abs(det(b.t - b.s, a - b.s)) / dis(b.s, b.t);
    return std::min(dis(a, b.s), dis(a, b.t));
}

std::vector<point> line_circle_intersect(cl a, cc b)//线与圆的交点
{//返回线与圆的交点
    if (sgn(point_to_segment(b.c, a) - b.r) > 0)
        return std::vector<point>();
    LD x = sqrtl(sqr(b.r) - sqr(point_to_line(b.c, a)));
    return std::vector<point>(
            {project_to_line(b.c, a) + (a.s - a.t).unit() * x, project_to_line(b.c, a) - (a.s - a.t).unit() * x});
}

LD circle_intersect_area(cc a, cc b)//求两个圆相交区域的面积
{
    LD d = dis(a.c, b.c);
    if (sgn(d - (a.r + b.r)) >= 0)return 0;
    if (sgn(d - abs(a.r - b.r)) <= 0)
    {
        LD r = std::min(a.r, b.r);
        return r * r * pi;
    }
    LD x = (d * d + a.r * a.r - b.r * b.r) / (2 * d),
            t1 = acosl(std::min((LD) 1, std::max((LD) -1, x / a.r))),
            t2 = acosl(std::min((LD) 1, std::max((LD) -1, (d - x) / b.r)));
    return sqr(a.r) * t1 + sqr(b.r) * t2 - d * a.r * sinl(t1);
}

std::vector<point> circle_intersect(cc a, cc b)//求两个圆的交
{
    if (a.c == b.c || sgn(dis(a.c, b.c) - a.r - b.r) > 0 || sgn(dis(a.c, b.c) - abs(a.r - b.r)) < 0)
        return {};
    point r = (b.c - a.c).unit();
    LD d = dis(a.c, b.c);
    LD x = ((sqr(a.r) - sqr(b.r)) / d + d) / 2;
    LD h = sqrtl(sqr(a.r) - sqr(x));
    if (sgn(h) == 0)return {a.c + r * x};
    return {a.c + r * x + r.rot90() * h, a.c + r * x - r.rot90() * h};
}

std::vector<point> tangent(cp a, cc b)//求一个点关于圆的切线
{
    circle p = make_circle(a, b.c);
    return circle_intersect(p, b);
}

std::vector<line> extangent(cc a, cc b)//求两圆的外切线
{
    std::vector<line> ret;
    if (sgn(dis(a.c, b.c) - abs(a.r - b.r)) <= 0)return ret;
    if (sgn(a.r - b.r) == 0)
    {
        point dir = b.c - a.c;
        dir = (dir * a.r / dir.len()).rot90();
        ret.push_back(line(a.c + dir, b.c + dir));
        ret.push_back(line(a.c - dir, b.c - dir));
    }
    else
    {
        point p = (b.c * a.r - a.c * b.r) / (a.r - b.r);
        std::vector pp = tangent(p, a), qq = tangent(p, b);
        if (pp.size() == 2 && qq.size() == 2)
        {
            if (sgn(a.r - b.r) < 0)
                std::swap(pp[0], pp[1]), std::swap(qq[0], qq[1]);
            ret.push_back(line(pp[0], qq[0]));
            ret.push_back(line(pp[1], qq[1]));
        }
    }
    return ret;
}

std::vector<line> intangent(cc a, cc b)//求两圆的内切线
{
    std::vector<line> ret;
    point p = (b.c * a.r + a.c * b.r) / (a.r + b.r);
    std::vector pp = tangent(p, a), qq = tangent(p, b);
    if (pp.size() == 2 && qq.size() == 2)
    {
        ret.push_back(line(pp[0], qq[0]));
        ret.push_back(line(pp[1], qq[1]));
    }
    return ret;
}

std::vector<point> cut(const std::vector<point> &c, line p)
{
    std::vector<point> ret;
    if (c.empty())return ret;
    int len = c.size();
    for (int i = 0; i < len; i++)
    {
        int j = (i + 1) % len;
        if (turn_left(p.s, p.t, c[i]))ret.push_back(c[i]);
        if (two_side(c[i], c[j], p))
            ret.push_back(line_intersect(p, line(c[i], c[j])));
    }
    return ret;
}

std::vector<point> convex_hull(std::vector<point> a)
{//凸包,字典序
    int n = (int) a.size(), cnt = 0;
    if (n < 2) return a;
    std::sort(a.begin(), a.end()); // less<pair>
    std::vector<point> ret;
    for (int i = 0; i < n; ++i)
    {
        while (cnt > 1
               && !turn_left(ret[cnt - 1], a[i], ret[cnt - 2]))
            --cnt, ret.pop_back();
        ++cnt, ret.push_back(a[i]);
    }
    int fixed = cnt;
    for (int i = n - 2; i >= 0; --i)
    {
        while (cnt > fixed
               && !turn_left(ret[cnt - 1], a[i], ret[cnt - 2]))
            --cnt, ret.pop_back();
        ++cnt, ret.push_back(a[i]);
    }
    ret.pop_back();
    return ret;
}

std::vector<point> minkovski(std::vector<std::vector<point>> a)
{
    if (a[0].size() == 1)
        return a[1];
    if (a[1].size() == 1)
        return a[0];
    for (int i = 0; i < 2; i++)a[i].push_back(a[i].front());
    int i[2] = {0, 0}, len[2] = {(int) a[0].size() - 1, (int) a[1].size() - 1};
    std::vector<point> ret;
    ret.push_back(a[0][0] + a[1][0]);
    do
    {
        int d = sgn(det(a[1][i[1] + 1] - a[1][i[1]], a[0][i[0] + 1] - a[0][i[0]])) >= 0;
        ret.push_back(a[d][i[d] + 1] - a[d][i[d]] + ret.back());
        i[d] = (i[d] + 1) % len[d];
    }
    while (i[0] || i[1]);
    return ret;
}

struct Convex
{
    int n;
    std::vector<point> a, upper, lower;
    std::map<point, int> mp;

    Convex(std::vector<point> _a) : a(_a)
    {
        n = a.size();
        int k = 0;
        for (int i = 1; i < n; i++)if (a[k] < a[i])k = i;
        for (int i = 0; i <= k; i++) lower.push_back(a[i]);
        for (int i = k; i < n; i++) upper.push_back(a[i]);
        upper.push_back(a[0]);
    }

    void pre_to_check_point()
    {
        for (int i = 0; i < n; i++)
            mp[a[i]] = i;
    }

    std::pair<LD, int> get_tan(std::vector<point> &con, point vec)
    {
        int l = 0, r = (int) con.size() - 2;
        for (; l + 1 < r;)
        {
            int mid = (l + r) / 2;
            if (sgn(det(con[mid + 1] - con[mid], vec)) > 0)r = mid;
            else l = mid;
        }
        return std::max(std::make_pair(det(vec, con[r]), r), std::make_pair(det(vec, con[0]), 0));
    }

    void upd_tan(cp p, int id, int &i0, int &i1)//辅助函数
    {
//        if (i0 == -1) i0 = id;
        if ((det(a[i0] - p, a[id] - p)) > 0) i0 = id;
//        if (i1 == -1) i1 = id;
        if ((det(a[i1] - p, a[id] - p)) < 0) i1 = id;
    }

    void search(int l, int r, point p, int &i0, int &i1)//辅助函数
    {
        if (l == r)return;
        upd_tan(p, l % n, i0, i1);
        int sl = sgn(det(a[l % n] - p, a[(l + 1) % n] - p));
        for (; l + 1 < r;)
        {
            int mid = (l + r) / 2;
            int smid = sgn(det(a[mid % n] - p, a[(mid + 1) % n] - p));
            if (smid == sl)l = mid;
            else r = mid;
        }
        upd_tan(p, r % n, i0, i1);
    }

    int search(point u, point v, int l, int r)//辅助函数
    {
        int sl = sgn(det(v - u, a[l % n] - u));
        for (; l + 1 < r;)
        {
            int mid = (l + r) / 2;
            int smid = sgn(det(v - u, a[mid % n] - u));
            if (smid == sl) l = mid;
            else r = mid;
        }
        return l % n;
    }

    //判定点是否在凸包内,在边界返回true
    bool contain(point p)
    {
        if (p.x < lower[0].x || p.x > lower.back().x)return false;
        int id = std::lower_bound(lower.begin(), lower.end(), point(p.x, -INF)) - lower.begin();
        if (lower[id].x == p.x)
        {
            if (lower[id].y > p.y)return false;
        }
        else if (det(lower[id - 1] - p, lower[id] - p) < 0)
            return false;
        id = std::lower_bound(upper.begin(), upper.end(), point(p.x, INF), std::greater<point>()) - upper.begin();
        if (upper[id].x == p.x)
        {
            if (upper[id].y < p.y)return false;
        }
        else if (det(upper[id - 1] - p, upper[id] - p) < 0)
            return false;
        return true;
    }

    int contain_strict(point p)//0代表在外面 1代表在里面 2代表在边上 3代表在点上
    {
        if (p.x < lower[0].x || p.x > lower.back().x)return 0;
        int id = std::lower_bound(lower.begin(), lower.end(), point(p.x, -INF)) - lower.begin();
        if (lower[id].x == p.x)
        {
            if (lower[id].y > p.y)return 0;
            else if (sgn(lower[id].y - p.y) == 0) return 3;
            else if (id + 1 < lower.size() && lower[id + 1].x == p.x && p.y < lower[id + 1].y)
                return 2;
            else if (id + 1 < lower.size() && lower[id + 1].x == p.x && p.y == lower[id + 1].y)
                return 3;
        }
        else if (det(lower[id - 1] - p, lower[id] - p) < 0)
            return 0;
        else if (sgn(det(lower[id - 1] - p, lower[id] - p)) == 0)
            return 2;
        id = std::lower_bound(upper.begin(), upper.end(), point(p.x, INF), std::greater<point>()) - upper.begin();
        if (upper[id].x == p.x)
        {
            if (upper[id].y < p.y)return 0;
            else if (upper[id].y == p.y)return 3;
            else if (id + 1 < upper.size() && upper[id + 1].x == p.x && p.y > upper[id + 1].y)
                return 2;
            else if (id + 1 < upper.size() && upper[id + 1].x == p.x && p.y == upper[id + 1].y)
                return 3;
        }
        else if (det(upper[id - 1] - p, upper[id] - p) < 0)
            return 0;
        else if (sgn(det(upper[id - 1] - p, upper[id] - p)) == 0)
            return 2;
        return 1;
    }

    bool get_tan(point p, int &i0, int &i1)
    {// 求点 p 关于凸包的两个切点, 如果在凸包外则有序返回编号, 共线的多个切点返回任意一个, 否则返回 false
        i0 = i1 = 0;
        int id = int(std::lower_bound(lower.begin(), lower.end(), p) - lower.begin());
        search(0, id, p, i0, i1);
        search(id, (int) lower.size(), p, i0, i1);
        id = int(std::lower_bound(upper.begin(), upper.end(), p, std::greater<point>()) - upper.begin());
        search((int) lower.size() - 1, (int) lower.size() - 1 + id, p, i0, i1);
        search((int) lower.size() - 1 + id, (int) lower.size() - 1 + (int) upper.size(), p, i0, i1);
        return true;
    }

    bool my_get_tan(point p, int &i0, int &i1)//自己魔改,常数大,可求点在凸包上的切线
    {
        if (p.x < lower[0].x || p.x > lower.back().x)
        {
            get_tan(p, i0, i1);
            return true;
        }
        int id = std::lower_bound(lower.begin(), lower.end(), point(p.x, -INF)) - lower.begin();
        if (lower[id].x == p.x)
        {
            if (lower[id].y > p.y)
            {
                get_tan(p, i0, i1);
                return true;
            }
            else if (sgn(lower[id].y - p.y) == 0)
            {
                i0 = (id - 1 + n) % n, i1 = (id + 1) % n;
                return true;
            }
            else if (id + 1 < lower.size() && lower[id + 1].x == p.x && p.y < lower[id + 1].y)
            {
                i0 = id, i1 = (id + 1) % n;
                return true;
            }
            else if (id + 1 < lower.size() && lower[id + 1].x == p.x && p.y == lower[id + 1].y)
            {
                i0 = id, i1 = (id + 2) % n;
                return true;
            }
        }
        else if (det(lower[id - 1] - p, lower[id] - p) < 0)
        {
            get_tan(p, i0, i1);
            return true;
        }
        else if (sgn(det(lower[id - 1] - p, lower[id] - p)) == 0)
        {
            i0 = (id - 1 + n) % n, i1 = id;
            return true;
        }
        id = std::lower_bound(upper.begin(), upper.end(), point(p.x, INF), std::greater<point>()) - upper.begin();
        if (upper[id].x == p.x)
        {
            if (upper[id].y < p.y)
            {
                get_tan(p, i0, i1);
                return true;
            }
            else if (upper[id].y == p.y)
            {
                i0 = id + lower.size() - 1;
                i1 = (i0 + 1 + n) % n;
                i0 = (i0 + n - 1) % n;
                return true;
            }
            else if (id + 1 < upper.size() && upper[id + 1].x == p.x && p.y > upper[id + 1].y)
            {
                i0 = id + lower.size() - 1;
                i1 = (i0 + 1) % n;
                i0 = (i0 + n) % n;
                return true;
            }
            else if (id + 1 < upper.size() && upper[id + 1].x == p.x && p.y == upper[id + 1].y)
            {
                i0 = n - 1, i1 = 1;
                return true;
            }
        }
        else if (det(upper[id - 1] - p, upper[id] - p) < 0)
        {
            get_tan(p, i0, i1);
            return true;
        }
        else if (sgn(det(upper[id - 1] - p, upper[id] - p)) == 0)
        {
            i0 = (id + lower.size() - 1 + n) % n;
            i1 = (i0 - 1 + n) % n;
            std::swap(i0, i1);
            return true;
        }
        return false;
    }

    // 求凸包上和向量 vec 叉积最大的点, 返回编号, 共线的多个切点返回任意一个
    int get_tan(point vec)
    {
        std::pair<LD, int> ret = get_tan(upper, vec);
        ret.second = (ret.second + (int) lower.size() - 1) % n;
        ret = std::max(ret, get_tan(lower, vec));
        return ret.second;
    }

    bool my_judge_intersect_segment(cp u, cp v)//判断线段与凸包是否有严格相交,即有无穿过内部,默认起点和终点不在凸包内部了
    {
        int u1, u2;
        my_get_tan(u, u1, u2);
        if (!turn_left(u, a[u2], v) || !turn_left(u, v, a[u1]))
            return false;
        my_get_tan(v, u1, u2);
        if (!turn_left(v, a[u2], u) || !turn_left(v, u, a[u1]))
            return false;
        return true;
    }
    // 求凸包和直线 u,v 的交点, 如果无严格相交返回 false. 如果有则是和 (i,next(i)) 的交点, 两个点无序, 交在点上不确定返回前后两条线段其中之一

    bool get_inter(point u, point v, int &i0, int &i1)
    {
        int p0 = get_tan(u - v), p1 = get_tan(v - u);
        if (sgn(det(v - u, a[p0] - u)) * sgn(det(v - u, a[p1] - u)) < 0)
        {
            if (p0 > p1)std::swap(p0, p1);
            i0 = search(u, v, p0, p1);
            i1 = search(u, v, p1, p0 + n);
            return true;
        }
        else return false;
    }
};

bool in_polygon(cp p, const std::vector<point> &po)//判断点是否在多边形里
{
    int n = (int) po.size();
    int cnt = 0;
    for (int i = 0; i < n; i++)
    {
        point a = po[i], b = po[(i + 1) % n];
        if (point_on_segment(p, line(a, b)))return true;
        int x = sgn(det(p - a, b - a)), y = sgn(a.y - p.y), z = sgn(b.y - p.y);
        if (x > 0 && y <= 0 && z > 0)++cnt;
        if (x < 0 && z <= 0 && y > 0)--cnt;

    }
    return cnt != 0;
}

bool In_Polygon(cp P, std::vector<point> &polygon)//判断点是否在多边形里面,射线法O(n)
{
    bool flag = false; //相当于计数
    point P1, P2; //多边形一条边的两个顶点
    int n = polygon.size();
    for (int i = 0, j = n - 1; i < n; j = i++)
    {
        //polygon[]是给出多边形的顶点
        P1 = polygon[i];
        P2 = polygon[j];
        if (point_on_segment(P, line(P1, P2)))return true;
        //前一个判断min(P1.y,P2.y)<P.y<=max(P1.y,P2.y)
        //这个判断代码我觉得写的很精妙 我网上看的 应该是大神模版
        //后一个判断被测点 在 射线与边交点 的左边
        if ((sgn(P1.y - P.y) > 0 != sgn(P2.y - P.y) > 0) &&
            sgn(P.x - (P.y - P1.y) * (P1.x - P2.x) / (P1.y - P2.y) - P1.x) < 0)
            flag = !flag;
    }
    return flag;
}

std::vector<point> Minkovski(std::vector<std::vector<point>> a)//可处理退化成线段的凸包
{                                                            //闵可夫斯基和
    std::vector<point> S;
    int n = a[0].size(), m = a[1].size();
    std::vector<point> A(n), B(m);
    for (int i = 0; i < n - 1; i++) A[i] = a[0][i + 1] - a[0][i];
    A[n - 1] = a[0][0] - a[0][n - 1];
    for (int i = 0; i < m - 1; i++) B[i] = a[1][i + 1] - a[1][i];
    B[m - 1] = a[1][0] - a[1][m - 1];                                                             //将两个凸包上的边向量都存入a,b中
    S.push_back(a[0][0] + a[1][0]);
    int p1 = 0, p2 = 0;
    while (p1 < n && p2 < m)
    {
        LD d = det(A[p1], B[p2]);
        if (d > 0)
            S.push_back(S.back() + A[p1++]);
        else if (d < 0)
            S.push_back(S.back() + B[p2++]);
        else
        {
            if (dot(A[p1], B[p1]) >= 0)
                S.push_back(S.back() + A[p1++]);
            else
            {
                auto [x, y] = A[p1];
                if (x > 0)
                    S.push_back(S.back() + A[p1++]);
                else if (x < 0)
                    S.push_back(S.back() + B[p2++]);
                else
                {
                    if (y > 0)
                        S.push_back(S.back() + A[p1++]);
                    else S.push_back(S.back() + B[p2++]);
                }
            }
        }
    }
    while (p1 < n)
        S.push_back(S.back() + A[p1++]);
    while (p2 < m)
        S.push_back(S.back() + B[p2++]);
    return S;
}

LD farthest_pair(std::vector<point> pu)//最远点对
{
    pu = convex_hull(pu);
    std::vector<std::vector<point>> ppu(2);
    std::vector<point> pu1;
    for (auto x: pu)
        pu1.push_back(x * -1);
    pu1 = convex_hull(pu1);
    ppu[0] = pu, ppu[1] = pu1;
    auto ret = Minkovski(ppu);
    LD ans = 0;
    for (auto x: ret)
        ans = std::max(ans, x.len());
    return ans;
}

LD closest_pair(std::vector<point> pu)//最近点对O(nlogn)
{
    int n = pu.size();
    std::sort(pu.begin(), pu.end());
    for (int i = 1; i < n; i++)
        if (pu[i] == pu[i - 1])
            return 0;
    std::set<point, decltype([](cp u, cp v)
    { return u.y == v.y ? u.x < v.x : u.y < v.y; })> s;
    LD ans = (pu[0] - pu[1]).len2();
    for (int i = 0, j = 0; i < n; i++)
    {
        if (ans == 0)
            break;
        auto it = s.begin();
        while (!s.empty() && j < i && sqr(pu[i].x - pu[j].x) >= ans)
            s.erase(pu[j++]);
        auto oit = s.lower_bound(pu[i]);
        it = oit;
        while (ans)
        {
            if (it == s.end())
                break;
            if (sqr(it->y - pu[i].y) >= ans)
                break;
            ans = std::min(ans, (pu[i] - *it).len2());
            it++;
        }
        it = oit;
        while (ans)
        {
            if (it == s.begin())
                break;
            it--;
            if (sqr(it->y - pu[i].y) >= ans)
                break;
            ans = std::min(ans, (pu[i] - *it).len2());
        }
        s.insert(pu[i]);
    }
    return sqrtl(ans);
}

void print(std::vector<point> res)
{
    std::cout << "print:\n";
    int cnt = 0;
    for (auto [x, y]: res)
        std::cout << ++cnt << ' ' << x << ' ' << y << std::endl;
    std::cout << "end\n";
}

int onRight(cl a, cp b)
{ return det(a.t - a.s, b - a.s) <= -eps; }//如果要包含点就-eps,不要就eps
/*
 丢直线 Ax+By+C<0;
if(sgn(b)==0)
            pl.push_back(line(point(-c/a,0),point(-c/a-b,a)));
        else pl.push_back(line(point(0,-c/b),point(-b,-c/b+a)));
 * */

std::vector<point> my_half_plane(std::vector<line> a)
{
    /*要加框取消注释 请注意对于一组解(x,y)x和y是否有要求
    a.push_back({{-INF,-INF},{INF,-INF}});
    a.push_back({{INF,-INF},{INF,INF}});
    a.push_back({{INF,INF},{-INF,INF}});
    a.push_back({{-INF,INF},{-INF,-INF}});
     */
    std::sort(a.begin(), a.end(), [&](auto x, auto y)
    {
        point u = x.t - x.s, v = y.t - y.s;
        if (u.on_up() != v.on_up())return u.on_up() < v.on_up();
        if (sgn(det(u, v)))
            return sgn(det(u, v)) > 0;
        else return sgn(det(x.t - y.s, y.t - y.s)) < 0;
    });
    int n = a.size();
    std::vector<line> que(n + 1);
    std::vector<point> p1(n + 1);
    std::vector<point> p2;
    int left = 0, right = 0;
    que[0] = a[0];
    std::vector<point> sb;
    for (int i = 1; i < n; i++)
    {
        if (sgn(det(a[i].t - a[i].s, a[i - 1].t - a[i - 1].s)) == 0)
            continue;
        while (left < right && onRight(a[i], p1[right]))right--;
        while (left < right && onRight(a[i], p1[left + 1]))left++;
        que[++right] = a[i];
        if (std::abs(det(que[right].t - que[right].s, que[right - 1].t - que[right - 1].s)) <= eps)
        {
            if (onRight(que[right], que[right - 1].s) &&
                dot(que[right].t - que[right].s, que[right - 1].t - que[right - 1].s) <= -eps)
                return sb;
            right--;
            if (!onRight(que[right], a[i].s))
                que[right] = a[i];
        }
        if (left < right)p1[right] = line_intersect(que[right], que[right - 1]);
    }
    while (left < right && onRight(que[left], p1[right]))right--;
    if (right - left <= 1)return sb;
    p1[left] = line_intersect(que[left], que[right]);
    for (int i = left; i <= right; i++)
        p2.push_back(p1[i]);
    return p2;
}
/*
 丢直线 Ax+By+C<0;
if(sgn(b)==0)
            pl.push_back(line(point(-c/a,0),point(-c/a-b,a)));
        else pl.push_back(line(point(0,-c/b),point(-b,-c/b+a)));
 * */
LD get_are(std::vector<point> pu)
{
    LD ans = 0;
    int n = pu.size();
    for (int i = 0; i < n; i++)
        ans += det(pu[i], pu[(i + 1) % n]);
    return ans / 2;
}

LD get_max_inscribed_circle(const std::vector<point> pu)
{
    int n = pu.size();
    std::vector<point> dt(n);
    for (int i = 0; i < n; i++)
        dt[i] = ((pu[(i + 1) % n] - (pu[i] + pu[(i + 1) % n]) / 2).rot90()).unit();
    LD l = 0, r = 1e7;
    std::function<bool(LD)> check = [&](LD r)
    {
        std::vector<line> pl;
        for (int i = 0; i < n; i++)
            pl.push_back({pu[i] + dt[i] * r, pu[(i + 1) % n] + dt[i] * r});
        auto po = my_half_plane(pl);
        return !po.empty();
    };
    while (r - l > 1e-4)
    {
        LD mid = (r + l) / 2;
        if (check(mid))
            l = mid;
        else r = mid;
    }
    return l;
}

long long get_ans(std::vector<point> pu)
{
    long long res = 0;
    LD max_x = -1e18, min_x = 1e18, max_y = -1e18, min_y = 1e18;
    LD len_x, len_y;
    for (int i = 0; i < 3; i++)
        max_x = std::max(max_x, pu[i].x), min_x = std::min(min_x, pu[i].x),
        max_y = std::max(max_y, pu[i].y), min_y = std::min(min_y, pu[i].y);
    len_x = max_x - min_x;
    len_y = max_y - min_y;
    if (len_x < len_y)
    {
        std::sort(pu.begin(), pu.end(), [&](auto u, auto v)
        { return u.x < v.x; });
        long long x_l, x_r;
        if (sgn(pu[0].x - (long long) roundl(pu[0].x)) == 0)
            x_l = (long long) roundl(pu[0].x) + 1;
        else x_l = floorl(pu[0].x) + 1;
        if (sgn(pu[2].x - (long long) roundl(pu[2].x)) == 0)
            x_r = (long long) roundl(pu[2].x) - 1;
        else x_r = floor(pu[2].x);
        for (long long i = x_l; i <= x_r; i++)
        {
            line li = line(point(i, 0), point(i, 1));
            point p1, p2;
            p1 = line_intersect(li, line(pu[0], pu[2]));
            if (i < pu[1].x)
                p2 = line_intersect(li, line(pu[0], pu[1]));
            else
                p2 = line_intersect(li, line(pu[1], pu[2]));
            if (p1.y > p2.y)
                std::swap(p1, p2);
            long long y_l, y_r;
            if (sgn(p1.y - (long long) roundl(p1.y)) == 0)
                y_l = (long long) roundl(p1.y) + 1;
            else y_l = floorl(p1.y) + 1;
            if (sgn(p2.y - (long long) roundl(p2.y)) == 0)
                y_r = (long long) roundl(p2.y) - 1;
            else y_r = floorl(p2.y);
            res += y_r - y_l + 1;
        }
    }
    else
    {
        std::sort(pu.begin(), pu.end(), [&](auto u, auto v)
        { return u.y < v.y; });
        long long y_l, y_r;
        if (sgn(pu[0].y - (long long) roundl(pu[0].y)) == 0)
            y_l = (long long) roundl(pu[0].y) + 1;
        else y_l = floorl(pu[0].y) + 1;
        if (sgn(pu[2].y - (long long) roundl(pu[2].y)) == 0)
            y_r = (long long) roundl(pu[2].y) - 1;
        else y_r = floor(pu[2].y);
        for (long long i = y_l; i <= y_r; i++)
        {
            line li = line(point(0, i), point(1, i));
            point p1, p2;
            p1 = line_intersect(li, line(pu[0], pu[2]));
            if (i < pu[1].y)
                p2 = line_intersect(li, line(pu[0], pu[1]));
            else
                p2 = line_intersect(li, line(pu[1], pu[2]));
            if (p1.x > p2.x)
                std::swap(p1, p2);
            long long x_l, x_r;
            if (sgn(p1.x - (long long) roundl(p1.x)) == 0)
                x_l = (long long) roundl(p1.x) + 1;
            else x_l = floorl(p1.x) + 1;
            if (sgn(p2.x - (long long) roundl(p2.x)) == 0)
                x_r = (long long) roundl(p2.x) - 1;
            else x_r = floorl(p2.x);
            res += x_r - x_l + 1;
        }
    }
    return res;
}
bool check(point a,point b,point c,point d)
{
    point p1=b-a;

    if(p1.x==0||p1.y==0)
    {
        if(sgn(point_to_line(a,line(c,d))-1)==0)
            return true;
    }
    long long res=0;
    long long t=std::gcd((long long)std::abs(p1.y),(long long)std::abs(p1.x));
    res+=t-1;
    p1=d-c;
    t=std::gcd((long long)std::abs(p1.y),(long long)std::abs(p1.x));
    res+=t-1;
    p1=a-d;
    t=std::gcd((long long)std::abs(p1.y),(long long)std::abs(p1.x));
    if(t!=1)
        return false;
    p1=b-c;
    t=std::gcd((long long)std::abs(p1.y),(long long)std::abs(p1.x));
    if(t!=1)
        return false;
    res+=4;
//    res*=2;
    res-=2;
    std::vector<point>pu;
    pu.push_back(a);
    pu.push_back(b);
    pu.push_back(c);
    pu.push_back(d);
    if(sgn(res- get_are(pu)*2)==0)
        return true;
    else return false;


}
void solve()
{
    int n;
    std::cin >> n;
    std::vector<point> pu(n);
    for (int i = 0; i < n; i++)
        pu[i].read();
    long long ans = 0;
    if (n < 4)
    {
        std::cout << "infinitely many" << std::endl;
        return;
    }
    for (int i = 0; i < n; i++)
    {
        point p1 = pu[i], p2 = pu[(i + 1) % n], p3 = pu[(i + 2) % n], p4 = pu[(i + 3) % n];
        if (!ray_intersect_judge(line(p1, p2), line(p4, p3)))
        {
            if(check(p1,p2,p3,p4))
                continue;
            std::cout << "infinitely many" << std::endl;
            return;
        }

        std::vector<point> pu1;
        pu1.push_back(p2);
        pu1.push_back(p3);
        pu1.push_back(line_intersect(line(p1, p2), line(p3, p4)));
        ans += get_ans(pu1);
//        pu[i].print();
//        std::cout<<get_ans(pu1)<<std::endl;
    }
    std::cout << ans << std::endl;
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0), std::cout.tie(0);
    std::cout << std::fixed << std::setprecision(9);
    int T = 1;
//    std::cin>>T;
    for (int i = 1; i <= T; i++)
        solve();
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 3748kb

input:

5
0 2
-2 0
-1 -3
1 -3
2 1

output:

23

result:

ok single line: '23'

Test #2:

score: 0
Accepted
time: 0ms
memory: 3816kb

input:

4
-7 -7
7 -7
7 7
-7 7

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3760kb

input:

4
-1000 1000
-1000 999
-999 999
-999 1000

output:

0

result:

ok single line: '0'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3936kb

input:

6
0 -901
900 -900
900 900
0 901
-900 900
-900 -900

output:

1457999998

result:

ok single line: '1457999998'

Test #5:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

6
900 -900
901 0
900 900
-900 900
-901 0
-900 -900

output:

1457999998

result:

ok single line: '1457999998'

Test #6:

score: 0
Accepted
time: 0ms
memory: 3988kb

input:

6
0 0
400 1
400 2
0 3
-400 2
-400 1

output:

1596

result:

ok single line: '1596'

Test #7:

score: 0
Accepted
time: 0ms
memory: 3740kb

input:

6
0 -901
900 -899
900 900
0 901
-900 900
-900 -899

output:

970921796

result:

ok single line: '970921796'

Test #8:

score: 0
Accepted
time: 1ms
memory: 3760kb

input:

6
2 -2
401 399
399 401
-2 2
-401 -399
-399 -401

output:

4794

result:

ok single line: '4794'

Test #9:

score: 0
Accepted
time: 1ms
memory: 3732kb

input:

6
399 -401
401 -399
2 2
-399 401
-401 399
-2 -2

output:

4794

result:

ok single line: '4794'

Test #10:

score: 0
Accepted
time: 0ms
memory: 3932kb

input:

4
-1 -1
-2 -2
-2 -3
-1 -2

output:

0

result:

ok single line: '0'

Test #11:

score: 0
Accepted
time: 0ms
memory: 3616kb

input:

4
0 0
0 1
-1 2
-1 1

output:

0

result:

ok single line: '0'

Test #12:

score: 0
Accepted
time: 1ms
memory: 3820kb

input:

48
5 -70
14 -68
22 -66
31 -63
39 -58
46 -52
52 -46
58 -39
63 -31
66 -22
68 -14
70 -5
70 5
68 14
66 22
63 31
58 39
52 46
46 52
39 58
31 63
22 66
14 68
5 70
-5 70
-14 68
-22 66
-31 63
-39 58
-46 52
-52 46
-58 39
-63 31
-66 22
-68 14
-70 5
-70 -5
-68 -14
-66 -22
-63 -31
-58 -39
-52 -46
-46 -52
-39 -58
...

output:

36

result:

ok single line: '36'

Test #13:

score: 0
Accepted
time: 0ms
memory: 3612kb

input:

4
-10 -10
-11 11
-11 10
-10 -11

output:

0

result:

ok single line: '0'

Test #14:

score: 0
Accepted
time: 0ms
memory: 3588kb

input:

4
10 -10
10 -11
11 10
11 11

output:

0

result:

ok single line: '0'

Test #15:

score: 0
Accepted
time: 0ms
memory: 3668kb

input:

4
5 5
6 5
-5 6
-6 6

output:

0

result:

ok single line: '0'

Test #16:

score: 0
Accepted
time: 0ms
memory: 3692kb

input:

4
100 -99
-99 -98
-100 -98
99 -99

output:

0

result:

ok single line: '0'

Test #17:

score: 0
Accepted
time: 0ms
memory: 3944kb

input:

4
0 1
-1 0
0 -1
1 0

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #18:

score: 0
Accepted
time: 1ms
memory: 3884kb

input:

4
-1000 0
0 -1000
1000 0
0 1000

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #19:

score: 0
Accepted
time: 0ms
memory: 3992kb

input:

4
-1000 1000
-1000 -1000
1000 -1000
1000 1000

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #20:

score: 0
Accepted
time: 0ms
memory: 3644kb

input:

4
0 0
0 2
-1 2
-1 1

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #21:

score: 0
Accepted
time: 0ms
memory: 3816kb

input:

4
-3 -2
-4 -2
-4 -3
-3 -4

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #22:

score: 0
Accepted
time: 0ms
memory: 3740kb

input:

4
6 -2
5 -2
4 -3
6 -3

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #23:

score: 0
Accepted
time: 0ms
memory: 3864kb

input:

48
4 -60
12 -59
19 -57
26 -54
33 -50
39 -45
45 -39
50 -33
54 -26
57 -19
59 -12
60 -4
60 4
59 12
57 19
54 26
50 33
45 39
39 45
33 50
26 54
19 57
12 59
4 60
-4 60
-12 59
-19 57
-26 54
-33 50
-39 45
-45 39
-50 33
-54 26
-57 19
-59 12
-60 4
-60 -4
-59 -12
-57 -19
-54 -26
-50 -33
-45 -39
-39 -45
-33 -50
...

output:

40

result:

ok single line: '40'

Test #24:

score: 0
Accepted
time: 0ms
memory: 3724kb

input:

4
7 3
7 4
5 4
6 3

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #25:

score: 0
Accepted
time: 0ms
memory: 3748kb

input:

4
-1000 0
-999 -1000
-998 0
-999 1000

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #26:

score: 0
Accepted
time: 0ms
memory: 3744kb

input:

4
0 -1000
1000 -999
0 -998
-1000 -999

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #27:

score: 0
Accepted
time: 0ms
memory: 3648kb

input:

3
999 -1000
1000 -1000
1000 -999

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #28:

score: 0
Accepted
time: 0ms
memory: 3736kb

input:

3
-2 -1
-2 -2
-1 -2

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #29:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

3
-1 0
0 1
-1 1

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #30:

score: 0
Accepted
time: 1ms
memory: 3992kb

input:

3
5 0
5 1
4 1

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #31:

score: 0
Accepted
time: 0ms
memory: 3984kb

input:

3
-777 -777
777 776
0 0

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #32:

score: 0
Accepted
time: 1ms
memory: 3880kb

input:

3
42 -13
42 -14
44 -13

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #33:

score: 0
Accepted
time: 1ms
memory: 3728kb

input:

3
-123 55
-122 57
-123 57

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #34:

score: 0
Accepted
time: 1ms
memory: 3868kb

input:

48
7 -99
19 -98
32 -94
44 -89
55 -83
66 -75
75 -66
83 -55
89 -44
94 -32
98 -19
99 -7
99 7
98 19
94 32
89 44
83 55
75 66
66 75
55 83
44 89
32 94
19 98
7 99
-7 99
-19 98
-32 94
-44 89
-55 83
-66 75
-75 66
-83 55
-89 44
-94 32
-98 19
-99 7
-99 -7
-98 -19
-94 -32
-89 -44
-83 -55
-75 -66
-66 -75
-55 -83
...

output:

156

result:

ok single line: '156'

Test #35:

score: 0
Accepted
time: 1ms
memory: 3884kb

input:

5
0 -1000
1000 -999
999 1000
-1000 1000
-1000 -999

output:

7986005002

result:

ok single line: '7986005002'

Test #36:

score: 0
Accepted
time: 1ms
memory: 3716kb

input:

6
-999 1000
-1000 0
-999 -1000
999 -1000
999 -1
998 999

output:

2992004004

result:

ok single line: '2992004004'

Test #37:

score: 0
Accepted
time: 0ms
memory: 3868kb

input:

12
-923 -771
-612 -869
778 -976
933 -289
930 553
907 731
845 822
324 920
-913 699
-957 596
-967 269
-946 -455

output:

609372

result:

ok single line: '609372'

Test #38:

score: 0
Accepted
time: 0ms
memory: 3820kb

input:

9
-497 -908
741 -696
978 -393
892 690
863 986
-510 934
-672 659
-972 60
-963 -762

output:

1867855

result:

ok single line: '1867855'

Test #39:

score: 0
Accepted
time: 1ms
memory: 3680kb

input:

21
-804 -988
-393 -993
806 -997
893 -982
986 -870
996 -744
1000 -268
1000 194
999 638
997 666
971 928
957 943
828 989
778 992
501 997
-692 1000
-964 991
-990 936
-993 521
-995 -929
-965 -956

output:

34183

result:

ok single line: '34183'

Test #40:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

15
-947 -801
-516 -997
427 -998
541 -998
566 -997
927 -966
990 -932
998 471
991 896
817 964
536 997
-715 998
-868 922
-993 664
-958 -492

output:

170756

result:

ok single line: '170756'

Test #41:

score: 0
Accepted
time: 1ms
memory: 3708kb

input:

5
1000 998
-999 1000
-1000 999
-998 -999
999 -1000

output:

5326010345

result:

ok single line: '5326010345'

Test #42:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

8
0 2
0 1
1 0
2 0
3 1
3 2
2 3
1 3

output:

0

result:

ok single line: '0'

Test #43:

score: 0
Accepted
time: 1ms
memory: 3820kb

input:

5
1000 0
999 1000
-1000 999
-1000 -1000
999 -1000

output:

7986005002

result:

ok single line: '7986005002'

Test #44:

score: 0
Accepted
time: 1ms
memory: 3676kb

input:

5
0 1000
-1000 999
-999 -1000
1000 -1000
1000 999

output:

7986005002

result:

ok single line: '7986005002'

Test #45:

score: 0
Accepted
time: 1ms
memory: 3872kb

input:

4
1000 1000
999 1000
999 999
1000 999

output:

0

result:

ok single line: '0'

Test #46:

score: 0
Accepted
time: 0ms
memory: 3820kb

input:

5
-1000 0
-999 -1000
1000 -999
1000 1000
-999 1000

output:

7986005002

result:

ok single line: '7986005002'

Test #47:

score: 0
Accepted
time: 1ms
memory: 3764kb

input:

50
883 0
876 110
855 219
820 325
773 425
714 519
643 604
562 680
473 745
375 798
272 839
165 867
55 881
-55 881
-165 867
-272 839
-375 798
-473 745
-562 680
-643 604
-714 519
-773 425
-820 325
-855 219
-876 110
-883 0
-876 -110
-855 -219
-820 -325
-773 -425
-714 -519
-643 -604
-562 -680
-473 -745
-3...

output:

19136

result:

ok single line: '19136'

Test #48:

score: 0
Accepted
time: 1ms
memory: 3740kb

input:

49
750 0
743 95
725 190
695 281
653 368
601 448
538 521
467 586
388 641
303 685
213 719
119 740
24 749
-72 746
-166 731
-259 703
-346 664
-429 615
-504 555
-571 486
-628 409
-675 325
-711 236
-736 143
-748 48
-748 -48
-736 -143
-711 -236
-675 -325
-628 -409
-571 -486
-504 -555
-429 -615
-346 -664
-2...

output:

14376

result:

ok single line: '14376'

Test #49:

score: 0
Accepted
time: 1ms
memory: 3640kb

input:

42
1000 0
988 149
955 294
900 433
826 563
733 680
623 781
500 866
365 930
222 974
74 997
-74 997
-222 974
-365 930
-499 866
-623 781
-733 680
-826 563
-900 433
-955 294
-988 149
-1000 0
-988 -149
-955 -294
-900 -433
-826 -563
-733 -680
-623 -781
-500 -866
-365 -930
-222 -974
-74 -997
74 -997
222 -97...

output:

34900

result:

ok single line: '34900'

Test #50:

score: 0
Accepted
time: 0ms
memory: 3740kb

input:

33
100 0
98 18
92 37
84 54
72 69
58 81
41 90
23 97
4 99
-14 98
-32 94
-49 86
-65 75
-78 61
-88 45
-95 28
-99 9
-99 -9
-95 -28
-88 -45
-78 -61
-65 -75
-50 -86
-32 -94
-14 -98
4 -99
23 -97
41 -90
58 -81
72 -69
84 -54
92 -37
98 -18

output:

515

result:

ok single line: '515'

Test #51:

score: 0
Accepted
time: 1ms
memory: 3988kb

input:

25
500 0
484 124
438 240
364 342
267 422
154 475
31 499
-93 491
-212 452
-318 385
-404 293
-464 184
-496 62
-496 -62
-464 -184
-404 -293
-318 -385
-212 -452
-93 -491
31 -499
154 -475
267 -422
364 -342
438 -240
484 -124

output:

24994

result:

ok single line: '24994'

Test #52:

score: 0
Accepted
time: 1ms
memory: 3888kb

input:

19
900 0
851 292
710 552
492 753
220 872
-74 896
-361 824
-609 662
-791 428
-887 148
-887 -148
-791 -428
-609 -662
-361 -824
-74 -896
220 -872
492 -753
710 -552
851 -292

output:

142538

result:

ok single line: '142538'

Test #53:

score: 0
Accepted
time: 0ms
memory: 3884kb

input:

7
800 0
498 625
-178 779
-720 347
-720 -347
-178 -779
498 -625

output:

1054757

result:

ok single line: '1054757'

Test #54:

score: 0
Accepted
time: 1ms
memory: 3724kb

input:

6
999 0
499 865
-499 865
-999 0
-499 -865
499 -865

output:

2588522

result:

ok single line: '2588522'

Test #55:

score: 0
Accepted
time: 3ms
memory: 3728kb

input:

5
1000 0
309 951
-809 587
-809 -587
309 -951

output:

5311708

result:

ok single line: '5311708'

Test #56:

score: 0
Accepted
time: 1ms
memory: 3692kb

input:

4
999 -999
999 -1000
1000 -1000
1000 -999

output:

0

result:

ok single line: '0'

Test #57:

score: 0
Accepted
time: 1ms
memory: 3884kb

input:

5
6 4
5 10
4 13
5 7
6 3

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #58:

score: 0
Accepted
time: 0ms
memory: 3692kb

input:

5
-4 6
-10 5
-13 4
-7 5
-3 6

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #59:

score: 0
Accepted
time: 1ms
memory: 3724kb

input:

5
-6 -4
-5 -10
-4 -13
-5 -7
-6 -3

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #60:

score: 0
Accepted
time: 0ms
memory: 3824kb

input:

5
4 -6
10 -5
13 -4
7 -5
3 -6

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #61:

score: 0
Accepted
time: 0ms
memory: 3884kb

input:

5
-6 4
-6 3
-5 7
-4 13
-5 10

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #62:

score: 0
Accepted
time: 0ms
memory: 3728kb

input:

5
-4 -6
-3 -6
-7 -5
-13 -4
-10 -5

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #63:

score: 0
Accepted
time: 0ms
memory: 3652kb

input:

5
6 -4
6 -3
5 -7
4 -13
5 -10

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #64:

score: 0
Accepted
time: 1ms
memory: 3888kb

input:

5
4 6
3 6
7 5
13 4
10 5

output:

infinitely many

result:

ok single line: 'infinitely many'

Test #65:

score: 0
Accepted
time: 0ms
memory: 3932kb

input:

4
-800 -100
-799 -103
-798 -105
-799 -102

output:

0

result:

ok single line: '0'

Test #66:

score: 0
Accepted
time: 0ms
memory: 3676kb

input:

4
602 -59
600 -60
603 -59
605 -58

output:

0

result:

ok single line: '0'

Test #67:

score: 0
Accepted
time: 0ms
memory: 3588kb

input:

4
-999 -999
-1000 -999
-1000 -1000
-999 -1000

output:

0

result:

ok single line: '0'

Test #68:

score: 0
Accepted
time: 1ms
memory: 3864kb

input:

4
-50 50
-52 51
-51 50
-49 49

output:

0

result:

ok single line: '0'

Test #69:

score: 0
Accepted
time: 1ms
memory: 3812kb

input:

4
5 0
6 0
7 1
6 1

output:

0

result:

ok single line: '0'

Test #70:

score: 0
Accepted
time: 1ms
memory: 3884kb

input:

4
3 -3
4 -4
5 -4
4 -3

output:

0

result:

ok single line: '0'