QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#597490#9434. Italian Cuisineucup-team3474#WA 0ms4036kbC++2326.0kb2024-09-28 17:55:412024-09-28 17:55:42

Judging History

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

  • [2024-09-28 17:55:42]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:4036kb
  • [2024-09-28 17:55:41]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std ;
#define vec point
typedef double db;    //卡精度就换long double,不过long double很慢
typedef long long ll;
const db eps = 1e-11;  //调参
const db pi = acos(-1.0);
const db inf = 40000;
int sgn(db x) {
    if (x < -eps)
        return -1;
    else if (x > eps)
        return 1;
    else
        return 0;
}
int cmp(db x, db y) { return sgn(x - y); }
void print(int num, db x) { cout << fixed << setprecision(num) << x << '\n'; }
struct point {
    db x, y;
    point() {}
    point(db x2, db y2) { x = x2, y = y2; }
    void input() {
        int x2, y2;
        cin >> x2 >> y2;
        x = x2;
        y = y2;
    }
    point operator+(const point &s) const { return (point){x + s.x, y + s.y}; }
    point operator-(const point &s) const { return (point){x - s.x, y - s.y}; }
    point operator*(const db &k) const { return (point){x * k, y * k}; }
    point operator/(const db &k) const { return (point){x / k, y / k}; }
    bool operator<(point b) const { return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x; }
    bool equal(point p2) { return cmp(x, p2.x) == 0 && cmp(y, p2.y) == 0; }
    db get_angle() { return atan2(y, x); }  //极角
    int getP() const { return sgn(y) == 1 || (sgn(y) == 0 && sgn(x) == -1); }
    db sq(db x) { return x * x; }
    db dis(point p)  //很吃精度,可能需要1e-10或更小的eps
    {
        return sqrtl(sq(x - p.x) + sq(y - p.y));  // check sqrt or sqrtl
    }
    db len() { return sqrtl(sq(x) + sq(y)); }
    db len2() { return sq(x) + sq(y); }
    point unit() {
        db w = len();
        return (point){x / w, y / w};
    }
    vec rotate_left()  //向量逆时针旋转90度
    {
        return vec(-y, x);
    }
    vec rotate_right()  //向量顺时针旋转90度
    {
        return vec(y, -x);
    }
    point move(db r)  //原点沿该点代表的向量方向移动r
    {
        db l = len();
        if (sgn(l) == 0)
            return *this;
        else
            return point(x * r / l, y * r / l);
    }
    vec rotate(db ang)  // ang是弧度制,逆时针旋转
    {
        return vec({x * cos(ang) - y * sin(ang), y * cos(ang) + x * sin(ang)});
    }
};
db cross(vec s, vec t) { return s.x * t.y - s.y * t.x; }              // 叉积
db dot(vec s, vec t) { return s.x * t.x + s.y * t.y; }                // 点积
db rad(vec p1, vec p2) { return atan2(cross(p1, p2), dot(p1, p2)); }  // 有向弧度
int in_mid(db k1, db k2, db k3)                                       // k3 在 [k1,k2] 内
{
    return cmp(k1, k3) * cmp(k2, k3) <= 0;
}
int in_mid(point p1, point p2, point p3) { return in_mid(p1.x, p2.x, p3.x) && in_mid(p1.y, p2.y, p3.y); }
int counter_clockwise(point p1, point p2, point p3)  // p1 p2 p3 逆时针 1 顺时针 -1 否则 0
{
    return sgn(cross(p2 - p1, p3 - p1));
}
struct line {
    point s, e;  // 点s在直线上,方向向量是e ,半平面在e左侧
    db ang;      //在运算时注意设置ang的值!这个非常重要,需要自己设置!
    line() {}
    line(point s2, point e2) {
        s = s2, e = e2;
        ang = e.get_angle();
    }
    int onRight(point p) { return sgn(cross(e, p - s)) < 0; }  //点p在直线右侧
    int include(point p) { return sgn(cross(e, p - s)) > 0; }
    point projection(point p)  // p在该直线上的投影点
    {
        db t = dot(e, p - s) / e.len();
        return s + e.move(t);
    }
    point reflection(point p)  // p关于直线的对称点
    {
        point p2 = projection(p);
        vec v = p2 - p;
        return p + v * 2;
    }
    db dis_point(point p)  //点到直线的距离
    {
        db t = dot(e, p - s) / e.len();
        point pp = s + e.move(t);
        return p.dis(pp);
    }
    db dis_segment_point(point p)  //点到线段的距离
    {
        point p1 = s;  //线段p1->p2
        point p2 = s + e;
        point p3 = projection(p);
        if (in_mid(p1, p2, p3))
            return p.dis(p3);
        else
            return min(p.dis(p1), p.dis(p2));
    }
    bool on_segment(point p)  // p在线段s->s+e上
    {
        return sgn((p.dis(s) + p.dis(s + e)) - s.dis(s + e)) == 0;  //
    }
    bool on_segment_jls(point q) {
        point k1 = s;
        point k2 = s + e;
        return in_mid(k1, k2, q) && sgn(cross(k1 - q, k2 - k1)) == 0;
    }
    int direction(point p2)  // p0 = s , p1 = s + e 判断p2与向量p0->p1的位置关系
    {
        point p0 = s;
        point p1 = s + e;
        db res = cross(p1 - p0, p2 - p0);
        if (sgn(res) > 0)
            return 1;  // p0->p1逆时针旋转得到p0->p2的方向
        else if (sgn(res) < 0)
            return 2;  // p0->p1顺时针旋转得到p0->p2的方向
        else {
            db res2 = dot(p1 - p0, p2 - p0);
            if (on_segment(p2))
                return 5;  // p2在线段p0->p1上
            else if (sgn(res2) < 0)
                return 3;  // p0->p1与p0->p2方向相反
            else
                return 4;  // p0->p1与p0->p2方向相同
        }
    }
    int Parallel_Orthogonal(line l2)  //判断两条直线平行、正交
    {
        if (sgn(cross(e, l2.e)) == 0)
            return 2;  //平行
        else if (sgn(dot(e, l2.e)) == 0)
            return 1;  //正交
        else
            return 0;
    }
    bool same_dir(line l2) { return Parallel_Orthogonal(l2) == 2 && sgn(dot(e, l2.e)) == 1; }
    point line_intersect(point s1, point t1, point s2, point t2)  // 直线交点(点+向量表示直线)
    {
        db x = cross(t2, s1 - s2) / cross(t1, t2);
        return s1 + t1 * x;
    }
    point line_intersect(line l2)  //直线交点(点+向量表示直线)
    {
        assert(sgn(cross(e, l2.e)) != 0);
        return line_intersect(s, e, l2.s, l2.e);
    }
    point segment_intersect(line l2)  //线段s->s+e与线段l2.s->l2.s+l2.e的交点
    {
        //保证向量长度不为0
        assert(sgn(cross(e, l2.e)) != 0);
        return line_intersect(s, e, l2.s, l2.e);
    }
    bool can_segment_intersect(line l2)  //线段s->s+e与线段l2.s->l2.s+l2.e
    {
        //保证向量长度不为0
        int t1 = sgn(cross(e, l2.s - s));
        int t2 = sgn(cross(e, (l2.s + l2.e) - s));
        int t3 = sgn(cross(l2.e, s - l2.s));
        int t4 = sgn(cross(l2.e, (s + e) - l2.s));
        if (on_segment(l2.s) || on_segment(l2.s + l2.e) || l2.on_segment(s) || l2.on_segment(s + e))  //端点在另一条线段上的情况
            return true;
        else if (t1 * t2 < 0 && t3 * t4 < 0)
            return true;
        else
            return false;
    }
    db segment_segment_dis(line l2)  //线段s->s+e与线段l2.s->l2.s+l2.e
    {
        if (can_segment_intersect(l2))
            return 0.0;
        else {
            db res = min({s.dis(l2.s), s.dis(l2.s + l2.e), (s + e).dis(l2.s), (s + e).dis(l2.s + l2.e)});
            point t = l2.projection(s);
            if (l2.on_segment(t)) res = min(res, s.dis(t));
            point t2 = l2.projection(s + e);
            if (l2.on_segment(t2)) res = min(res, (s + e).dis(t2));
            point t3 = projection(l2.s);
            if (on_segment(t3)) res = min(res, l2.s.dis(t3));
            point t4 = projection(l2.s + l2.e);
            if (on_segment(t4)) res = min(res, (l2.s + l2.e).dis(t4));
            return res;
        }
    }
    line trans(db r)  //半平面u向内平移r
    {
        line v;
        v.s = s + e.rotate_left().move(r);
        v.e = e;
        v.ang = e.get_angle();  //注意设置ang的值
        return v;
    }
    line perpendicular_bisector()  //线段s->s+e的中垂线
    {
        point p = (s + (s + e)) / 2;
        vec p_e = e.rotate_left();
        line l2;
        l2.s = p;
        l2.e = p_e;
        return l2;
    }
};
int compare_angle(vec v1, vec v2) { return v1.getP() < v2.getP() || (v1.getP() == v2.getP() && sgn(cross(v1, v2)) > 0); }
bool operator<(line l1, line l2) {
    if (l1.same_dir(l2)) return l2.include(l1.s);
    return compare_angle(l1.e, l2.e);
}
struct Polygon {
    vector<point> pp;
    Polygon() {}
    Polygon(int n) { pp.resize(n); }
    int size() const { return pp.size(); }
    void resize(int n) { pp.resize(n); }
    point operator[](int id) const {
        if (id < 0 || id >= size())
            assert(false);
        else
            return pp[id];
    }
    point &operator[](int id) { return pp[id]; }
    // 凸包
    // Andrew算法
    // 按照x优先的顺序排序(坐标从小到大)
    // 从第一个点开始遍历,如果下一个点在栈顶的两个元素所连成直线的左边,那么就入栈
    // 否则如果在右边,说明凸包有更优的方案,上次的点出栈,并直到新点在栈顶两个点所在的直线的左边为止
    // 这样求得下凸包,类似方法求得上凸包。
    void Convex_Hull(vector<point> P, vector<point> &res, int flag = 1)  // flag = 0 不严格(存在三点共线) flag = 1 严格(不存在三点共线)
    {
        int n = P.size();
        res.resize(0);
        res.resize(n * 2);
        sort(P.begin(), P.end());
        int now = -1;
        for (int i = 0; i < (int)P.size(); i++) {
            while (now > 0 && sgn(cross(res[now] - res[now - 1], P[i] - res[now - 1])) < flag) now--;
            res[++now] = P[i];
        }
        int pre = now;
        for (int i = n - 2; i >= 0; i--) {
            while (now > pre && sgn(cross(res[now] - res[now - 1], P[i] - res[now - 1])) < flag) now--;
            res[++now] = P[i];
        }
        res.resize(now);
    }
    // tested on gym104633C
    // 半平面交
    // 排序增量算法
    // 1.以逆时针为正方向,建边。(输入方向不确定时,可用叉乘求面积看正负得知输入的顺逆方向。)
    // 2.对线段根据极角排序。
    // 3.去除极角相同的情况下,位置在右边的边。
    // 4.用双端队列储存线段集合L,遍历所有线段。
    // 5.判断该线段加入后对半平面交的影响,(对双端队列的头部和尾部进行判断,因为线段加入是有序的。)。
    // 6.如果某条线段对于新的半平面交没有影响,则从队列中剔除掉。
    // 7.最后剩下的线段集合L,即使最后要求的半平面交。
    int Half_Plane_Intersection(vector<line> L, vector<point> &res)  // L.push_back({p[i] , p[(i + 1) % m] - p[i]}) ;
    {
        //一般需要加入边界
        //读入的范围是1e9,边界的范围设置为1e19,因为交点的坐标是平方级别。
        int n = L.size();
        for (auto &u : L) u.ang = u.e.get_angle();
        sort(L.begin(), L.end());
        int l = 0, r = 0;
        vector<point> p(n);
        vector<line> q(n);
        q[0] = L[0];
        for (int i = 1; i <= n - 1; i++) {
            while (l < r && L[i].onRight(p[r - 1])) r--;
            while (l < r && L[i].onRight(p[l])) l++;
            q[++r] = L[i];
            if (sgn(cross(q[r].e, q[r - 1].e)) == 0) {
                if (!q[r].same_dir(q[r - 1])) return 0;
                r--;
                if (!q[r].onRight(L[i].s)) q[r] = L[i];
            }
            if (l < r) p[r - 1] = q[r - 1].line_intersect(q[r]);
        }
        while (l < r && q[l].onRight(p[r - 1])) r--;
        if (r - l <= 1) return 0;  // 交不存在
        res.resize(0);
        p[r] = q[l].line_intersect(q[r]);
        for (int i = l; i <= r; i++) res.push_back(p[i]);
        return 1;
    }
    db perimeter(vector<point> A)  // 多边形用 vector<point> 表示 , 逆时针
    {
        db ans = 0;
        for (int i = 0; i < (int)A.size(); i++) ans += A[i].dis(A[(i + 1) % (int)A.size()]);
        return ans;
    }
    db area()  // 多边形用 vector<point> 表示 , 逆时针
    {
        db ans = 0;
        for (int i = 0; i < (int)pp.size(); i++) ans += cross(pp[i], pp[(i + 1) % (int)pp.size()]);
        return fabs(ans) / 2;
    }
    bool is_convex(vector<point> A)  // 多边形用 vector<point> 表示 , 逆时针
    {
        int n = A.size();
        assert(n >= 3);
        bool flag = true;
        for (int i = 0; i < n; i++) {
            int lst = (i - 1 + n) % n;
            int nxt = (i + 1) % n;
            if (sgn(cross(A[lst] - A[i], A[nxt] - A[i])) > 0) flag = false;
        }
        return flag;
    }
    int contain_point(point p0)  // 不一定是凸的 2 内部 1 边界 0 外部
    {
        int n = pp.size();
        int res = 0;
        for (int i = 0; i < n; i++) {
            point u = pp[(i - 1 + n) % n];
            point v = pp[i];
            line l;
            l.s = u;
            l.e = v - u;
            if (l.on_segment(p0)) return 1;
            if (cmp(u.y, v.y) > 0) swap(u, v);
            if (cmp(u.y, p0.y) >= 0 || cmp(v.y, p0.y) < 0) continue;
            if (sgn(cross(u - v, p0 - v)) < 0) res ^= 1;
        }
        return res << 1;
    }
    db Convex_Diameter() {
        //原理是凸多边形的凸函数性质
        int now = 0;
        int n = pp.size();
        db res = 0;
        for (int i = 0; i < n; i++) {
            now = max(now, i);
            while (true) {
                db k1 = pp[i].dis(pp[now % n]);
                db k2 = pp[i].dis(pp[(now + 1) % n]);
                res = max({res, k1, k2});
                if (cmp(k2, k1) > 0)
                    now++;
                else
                    break;
            }
        }
        return res;
    }
    Polygon line_cut_convex(point p1, point p2) {
        //在已有凸多边形基础上新加一个半平面p1->p2
        //问之后的凸多边形
        int n = pp.size();
        line l;
        l.s = p1;
        l.e = p2 - p1;
        Polygon res;
        for (int i = 0; i < n; i++) {
            int w1 = counter_clockwise(p1, p2, pp[i]);
            int w2 = counter_clockwise(p1, p2, pp[(i + 1) % n]);
            if (w1 >= 0) res.pp.push_back(pp[i]);
            line l2;
            l2.s = pp[i];
            l2.e = pp[(i + 1) % n] - pp[i];
            if (w1 * w2 < 0) res.pp.push_back(l.line_intersect(l2));
        }
        return res;
    }
} polygon;
struct circle {
    point o;
    db r;
    db area() { return pi * r * r; }
    int inside(point p2) { return cmp(r, o.dis(p2)); }
    circle get_circle(point p1, point p2, point p3)  //三点确定一个圆
    {
        db a1 = p2.x - p1.x, b1 = p2.y - p1.y, c1 = (a1 * a1 + b1 * b1) / 2;
        db a2 = p3.x - p1.x, b2 = p3.y - p1.y, c2 = (a2 * a2 + b2 * b2) / 2;
        db d = a1 * b2 - a2 * b1;
        point o = (point){p1.x + (c1 * b2 - c2 * b1) / d, p1.y + (a1 * c2 - a2 * c1) / d};
        return (circle){o, p1.dis(o)};
    }
    vector<point> Tangent_Point_Circle(point p)  //沿圆的逆时针方向给出切点,点在圆上也给出两个
    {
        //相似三角形
        assert(cmp(p.dis(o), r) >= 0);
        db a = (p - o).len();
        assert(sgn(a) >= 0);
        db b = r * r / a;
        db c = sqrt(max(db(0.0), r * r - b * b));
        point k = (p - o).unit();
        point m = o + k * b;
        point v = k.rotate_left() * c;
        return {m - v, m + v};
    }
    int check_pos_circle_circle(circle c1, circle c2)  //返回两个圆的公切线数量,即位置关系
    {
        //根据圆心之间的距离及两个圆的半径判断
        if (cmp(c1.r, c2.r) < 0) swap(c1, c2);
        db d = c1.o.dis(c2.o);
        int w1 = cmp(d, c1.r + c2.r);
        int w2 = cmp(d, c1.r - c2.r);
        if (w1 > 0)
            return 4;  //相离
        else if (w1 == 0)
            return 3;  //外切
        else if (w2 > 0)
            return 2;  //相交
        else if (w2 == 0)
            return 1;  //内切
        else
            return 0;  //内含
    }
    vector<point> get_circle_line(line l)  //圆与直线求交点,沿l.e方向的顺序给出交点,相切给出两个
    {
        //投影后勾股定理
        point k = l.projection(o);
        db d = r * r - (k - o).len2();
        if (sgn(d) < 0) return {};
        vec v = l.e.unit() * sqrtl(max((db)0.0, d));
        return {k - v, k + v};
    }
    vector<point> get_circle_circle(circle c1, circle c2)  //两个圆的交点,沿圆c1逆时针给出,相切给出两个
    {
        //余弦定理
        int pos = check_pos_circle_circle(c1, c2);
        if (pos == 0 || pos == 4) return {};
        db a = (c2.o - c1.o).len2();
        db cosA = (c1.r * c1.r + a - c2.r * c2.r) / (2 * c1.r * sqrtl(max(a, (db)0.0)));
        db b = c1.r * cosA;
        db c = sqrtl(max((db)0.0, c1.r * c1.r - b * b));
        point k = (c2.o - c1.o).unit();
        point m = c1.o + k * b;
        vec v = k.rotate_left() * c;
        return {m - v, m + v};
    }
    circle Incircle_of_a_Triangle(point p1, point p2, point p3)  //三角形p1p2p3内接圆
    {
        //角平分线求交点,点到直线距离
        line l1;
        l1.s = p1;
        l1.e = (p2 - p1).unit() + (p3 - p1).unit();
        line l2;
        l2.s = p2;
        l2.e = (p1 - p2).unit() + (p3 - p2).unit();
        point p = l1.line_intersect(l2);
        line l3;
        l3.s = p1;
        l3.e = p2 - p1;
        circle cc;
        cc.o = p;
        cc.r = l3.dis_point(p);
        return cc;
    }
    circle Circumscribed_Circle_of_a_Triangle(point p1, point p2, point p3)  //三角形p1p2p3外接圆
    {
        //垂直平分线求交点,点到直线距离
        line l1;
        l1.s = p1 + (p2 - p1) / 2;
        l1.e = (p2 - p1).rotate_left();  //顺时针或逆时针旋转90度均可,因为是直线求交
        line l2;
        l2.s = p2 + (p3 - p2) / 2;
        l2.e = (p3 - p2).rotate_left();
        point p = l1.line_intersect(l2);
        circle cc;
        cc.o = p;
        cc.r = p.dis(p1);
        return cc;
    }
    vector<line> Tangent_out_Circle_Circle(circle c1, circle c2)  //外切线
    {
        //相似三角形
        int pos = check_pos_circle_circle(c1, c2);
        if (pos == 0) return {};
        if (pos == 1) {
            point k = get_circle_circle(c1, c2)[0];
            vec v = k - c1.o;
            v = v.rotate_left();
            line l;
            l.s = k;
            l.e = v;
            return {l};
        }
        if (cmp(c1.r, c2.r) == 0) {
            vec v = (c2.o - c1.o).rotate_left().unit() * c1.r;
            vec p1 = c1.o + v;
            line l1;
            l1.s = p1;
            l1.e = c2.o - c1.o;
            vec p2 = c1.o - v;
            line l2;
            l2.s = p2;
            l2.e = c2.o - c1.o;
            return {l1, l2};
        } else {
            vec v = c2.o - c1.o;
            v = v.unit() * (c1.o.dis(c2.o) * c1.r / (c1.r - c2.r));
            point H = c1.o + v;
            vector<point> pp1 = c1.Tangent_Point_Circle(H);
            line l1;
            l1.s = H;
            l1.e = pp1[0] - H;
            line l2;
            l2.s = H;
            l2.e = pp1[1] - H;
            return {l1, l2};
        }
    }
    vector<line> Tangent_in_Circle_Circle(circle c1, circle c2)  //内切线
    {
        int pos = check_pos_circle_circle(c1, c2);
        if (pos <= 2) return {};
        if (pos == 3) {
            point k = get_circle_circle(c1, c2)[0];
            vec v = k - c1.o;
            v = v.rotate_left();
            line l;
            l.s = k;
            l.e = v;
            return {l};
        }
        db t = c1.r / (c1.r + c2.r) * c1.o.dis(c2.o);
        point p = c1.o + (c2.o - c1.o).unit() * t;
        vector<point> pp1 = c1.Tangent_Point_Circle(p);
        line l1;
        l1.s = p;
        l1.e = pp1[0] - p;
        line l2;
        l2.s = p;
        l2.e = pp1[1] - p;
        return {l1, l2};
    }
    vector<line> Tangent_Circle_Circle(circle c1, circle c2)  //两个圆的公切线
    {
        //外切线和内切线一起考虑
        if (cmp(c1.r, c2.r) < 0) swap(c1, c2);
        vector<line> A = Tangent_out_Circle_Circle(c1, c2);
        vector<line> B = Tangent_in_Circle_Circle(c1, c2);
        for (auto u : B) A.push_back(u);
        return A;
    }
    db get_area_of_Circle_Triangle(circle c1, point p2, point p3) {
        //圆c1与三角形c1 p2 p3的交
        //有向面积,可能为负
        point k = c1.o;
        c1.o = c1.o - k;
        p2 = p2 - k;
        p3 = p3 - k;
        int pos1 = c1.inside(p2);
        int pos2 = c1.inside(p3);
        line l;
        l.s = p2;
        l.e = p3 - p2;
        vector<point> pp = c1.get_circle_line(l);
        if (pos1 >= 0) {
            if (pos2 >= 0) return cross(p2, p3) / 2;
            return c1.r * c1.r * rad(pp[1], p3) / 2 + cross(p2, pp[1]) / 2;
        } else if (pos2 >= 0) {
            return c1.r * c1.r * rad(p2, pp[0]) / 2 + cross(pp[0], p3) / 2;
        } else {
            line l;
            l.s = p2;
            l.e = p3 - p2;
            int pos = cmp(c1.r, l.dis_segment_point(c1.o));
            if (pos <= 0) return c1.r * c1.r * rad(p2, p3) / 2;
            return cross(pp[0], pp[1]) / 2 + c1.r * c1.r * (rad(p2, pp[0]) + rad(pp[1], p3)) / 2;
        }
    }
    db get_area_of_Circle_Polygon(circle c1, vector<point> pp)  // pp按照逆时针给出
    {
        //转成三角形和圆求有向面积交
        int n = pp.size();
        db res = 0;
        for (int i = 0; i < n; i++) {
            point now = pp[i];  //三角形o pp[i] pp[(i + 1) % n] 需要按照顺序给出
            point nxt = pp[(i + 1) % n];
            res += get_area_of_Circle_Triangle(c1, now, nxt);  //已经除2
        }
        return fabs(res);
    }
    db get_area_of_Circle_Circle(circle c1, circle c2)  //两个圆的相交面积
    {
        //扇形减去四边形面积
        if (cmp(c1.r, c2.r) < 0) swap(c1, c2);
        int pos = check_pos_circle_circle(c1, c2);
        if (pos >= 3) return 0.0;
        if (pos <= 1) return c2.area();
        vector<point> pp = get_circle_circle(c1, c2);
        db S1 = fabs(2.0 * rad(pp[0] - c1.o, c2.o - c1.o)) * c1.r * c1.r / 2;
        db S2 = fabs(2.0 * rad(pp[0] - c2.o, c1.o - c2.o)) * c2.r * c2.r / 2;
        db S3 = fabs(cross(pp[0] - c1.o, c2.o - c1.o));
        return S1 + S2 - S3;
    }
} c;
db closest_point(vector<point> &A, int l, int r)  //先按照x轴排序
{
    if (r - l <= 5) {
        db res = 1e20;
        for (int i = l; i <= r; i++)
            for (int j = i + 1; j <= r; j++) res = min(res, A[i].dis(A[j]));
        return res;
    }
    int mid = (l + r) / 2;
    db res = min(closest_point(A, l, mid), closest_point(A, mid + 1, r));
    vector<point> B;
    for (int i = l; i <= r; i++)
        if (cmp(fabs(A[i].x - A[mid].x), res) <= 0) B.push_back(A[i]);
    sort(B.begin(), B.end(), [&](point p1, point p2) { return cmp(p1.y, p2.y) < 0; });
    for (int i = 0; i < B.size(); i++)
        for (int j = i + 1; j < B.size() && B[j].y - B[i].y < res; j++) res = min(res, B[i].dis(B[j]));
    return res;
}
void solve()
{
    int n ;
    cin >> n ;
    point o ;
    o.input() ;
    int r ;
    cin >> r ;
    vector<pair<long long , long long>> z(n) ;
    vector<point> p(n) ;
    for(int i = 0 ; i < n ; i ++)  
    {
        cin >> z[i].first >> z[i].second ;
        p[i] = {z[i].first , z[i].second} ;
        
    }

    auto cross2 = [&](pair<long long , long long> u , pair<long long , long long> v)
    {
        return u.first * v.second - u.second * v.first ;
    } ;

    long long all = 0 ;
    for (int i = 0; i < (int)p.size(); i++) all += cross2(z[i], z[(i + 1) % n]);

    vector<long long> pre(n , 0ll) ;
    for(int i = 0 ; i < n ; i ++)  pre[i] = cross2(z[i] , z[(i + 1) % n]) ;
    for(int i = 1 ; i < n ; i ++)  pre[i] += pre[i - 1] ;
    auto query = [&](int l , int r)
    {
        if(l < r)
        {
            long long q = pre[r - 1] ;
            if(l > 0)  q -= pre[l - 1] ;
            q += cross2(z[r] , z[l]) ;
            return q ;
        }
        long long q = 0 ;
        q += pre[n - 1] - pre[l - 1] ;
        if(r > 0)  q += pre[r - 1] ;
        q += cross2(z[r] , z[l]) ;
        return q ;
    } ;

    long long ans = 0 ;
    auto ask = [&](int l , int r)
    {
        assert((l + 1) % n != r) ;
        assert((r + 1) % n != l) ;
        long long area = query(l , r) ;
        long long area2 = all - area ;
        if(sgn(cross(p[r] - p[l] , o - p[l])) == -1)  return area2 ;
        return area ;
    } ;
    auto intersect = [&](int i , int j)
    {
        // cout<<i<<" "<<j<<endl;  
        line l ;
        l.s = p[i] ;
        l.e = p[j] - p[i] ;
        db d = l.dis_point(o) ;
        return d + eps< r ;
    };

    auto getangle = [&](db x,db y){
        db ans=0;
        db angle=acos(x/sqrt(x*x+y*y));
        if(y>0) ans=angle;
        else ans=2*acos(-1)-angle;
        return ans;
    };

    auto cmp = [&](point u,point v){
        return getangle(u.x,u.y)+eps<getangle(v.x,v.y);
    };

    for(int i=0;i<n;i++) z.push_back(z[i]),p.push_back(p[i]);
    long long res=0;
    int j=1;
    // cout<<114514<<endl;
    for(int i=0;i<n;i++){
        j=max(j,i+1);
        while(intersect(i,j+1)==0){
            point pp1={p[j].x-p[i].x,p[j].y-p[i].y},pp2={o.x-p[i].x,o.y-p[i].y},pp3={p[j+1].x-p[i].x,p[j+1].y-p[i].y};
            if(cmp(pp1,pp2)&&cmp(pp2,pp3)) break;
            pair<long long,long long> p1={z[j].first-z[i].first,z[j].second-z[i].second};
            pair<long long,long long> p2={z[j+1].first-z[i].first,z[j+1].second-z[i].second};
            long long sz=cross2(p1,p2);
            // cout<<sz<<endl;
            res+=sz;
            j++;
        }
        // cout<<i<<" "<<j<<endl;
        ans=max(ans,res);
        pair<long long,long long> p1={z[j].first-z[i].first,z[j].second-z[i].second};
        pair<long long,long long> p2={z[j].first-z[i+1].first,z[j].second-z[i+1].second};
            long long sz=cross2(p1,p2);
            res-=sz;
            // cout<<ans<<endl;
    }
    
    cout << ans << '\n' ;
}
int main()
{
    std::ios::sync_with_stdio(false) , cin.tie(0) ;

    int T ;
    cin >> T ;
    while (T --)  solve() ;
    return 0 ;
}

详细

Test #1:

score: 100
Accepted
time: 0ms
memory: 4036kb

input:

3
5
1 1 1
0 0
1 0
5 0
3 3
0 5
6
2 4 1
2 0
4 0
6 3
4 6
2 6
0 3
4
3 3 1
3 0
6 3
3 6
0 3

output:

5
24
0

result:

ok 3 number(s): "5 24 0"

Test #2:

score: -100
Wrong Answer
time: 0ms
memory: 3832kb

input:

1
6
0 0 499999993
197878055 -535013568
696616963 -535013568
696616963 40162440
696616963 499999993
-499999993 499999993
-499999993 -535013568

output:

286862654137719264

result:

wrong answer 1st numbers differ - expected: '0', found: '286862654137719264'