template/zhongzihao/geometry

#include<bits/stdc++.h>

const double eps = 1e-9;
const double PI = acos(-1.0);
const double INF = 1e100;

inline int sig(double p){
    return (p > eps) - (p < -eps);
}

inline double sqr(double p){return p * p;}

class P{
public:
    double x, y;
    explicit P (double x = 0, double y = 0): x(x), y(y){}
    P operator + (const P &p)const{return P (x + p.x, y + p.y);}
    P operator - (const P &p)const{return P (x - p.x, y - p.y);}
    P operator * (const double &p)const{return P (x * p, y * p);}
    friend P operator * (const double &d, const P &p){return P (d * p.x, d * p.y);}
    P operator / (const double &p)const{return P (x / p, y / p);}
    double operator ^ (const P &p)const{return x * p.y - y * p.x;}
    double operator % (const P &p)const{return x * p.x + y * p.y;}
    double abs2()const{return *this % *this;}
    double abs()const{return std::sqrt(abs2());}
    double angle()const{return std::atan2(y, x);}
    
    // 逆时针旋转 rad 弧度 
    P rot(const double &rad)const{
        double sin = std::sin(rad), cos = std::cos(rad);
        return P (x * cos - y * sin, x * sin + y * cos);
    }
    
    P rot90()const{
        return P (-y, x);
    }
    
    bool operator < (const P &p)const{
        if (sig(x - p.x)) return x < p.x;
        return y < p.y;
    }
    
    bool operator == (const P &p)const{
        return !sig(x - p.x) && !sig(y - p.y);
    }
    
    void read(){
        scanf("%lf%lf", &x, &y);
    }
    
    void write(){
        printf("%.10lf %.10lf\n", x, y);
    }
};

class L{
public:
    P p, v;
    double angle;
    
    L (){}
    L (P a, P b):p(a), v(b - a){angle = std::atan2(v.y, v.x);}
    
    bool operator < (const L &l)const{
        return angle < l.angle;
    }
    
    P point(double t){
        return p + v * t;
    }
};

class C{
public:
    P o;
    double r;
    
    C (){}
    C (P o, double r):o(o), r(r){}
    
    P point(double angle){
        return P (o + P (std::cos(angle), std::sin(angle)) * r);
    }
};

double rad(P p1, P p2){
    return std::acos((p1 % p2) / (p1.abs() * p2.abs()));
}

P normal(P p){
    return p.rot90() / p.abs();
}

// v1 和 v2 是两直线的方向向量 
double isLL(L l1, L l2){
    P u = l2.p - l1.p;
    return (u ^ l2.v) / (l1.v ^ l2.v); // 返回交点在 p1v1 上的位置,可以用来判断射线、线段等
}

// 返回有向距离,q 在直线逆时针方向为正 
double disLP(L l, P p){
    return l.v ^ (p - l.p) / l.v.abs();
}

double disSP(P p1, P p2, P q){
    if (p1 == p2) return (q - p1).abs();
    P v1 = p2 - p1, v2 = q - p1, v3 = q - p2;
    if (sig(v1 % v2) < 0) return v2.abs();
    if (sig(v1 % v3) > 0) return v3.abs();
    return std::abs(v1 ^ v2) / v1.abs();
}

P proj(L l, P p){
    return l.p + l.v * (l.v % (p - l.p) / l.v.abs2());
}

P symmetry(L l, P p){
    return 2 * proj(l, p) - p;
}

//判断线段是否严格相交(包括严格重合) 
bool crsSS(P p1, P p2, P q1, P q2){
    double c1 = (p2 - p1) ^ (q1 - p1);
    double c2 = (p2 - p1) ^ (q2 - p1);
    if (!sig(c1) && !sig(c2)){
        if (p2 < p1) std::swap(p1, p2);
        if (q2 < q1) std::swap(q1, q2);
        return std::max(p1, q1) < std::min(p2, q2);
    }
    double c3 = (q2 - q1) ^ (p1 - q1);
    double c4 = (q2 - q1) ^ (p2 - q1);
    return sig(c1) * sig(c2) < 0 && sig(c3) * sig(c4) < 0;
}

bool onSeg(P p1, P p2, P q){
    double len = (q - p1).abs();
    if (!sig(len)) return true;
    p1 = p1 - q, p2 = p2 - q;
    return !sig((p1 ^ p2) / len) && sig(p1 % p2) <= 0;
}

bool onRay(P p1, P p2, P q){
    double len = (q - p1).abs();
    if (!sig(len)) return true;
    p1 = q - p1, p2 = q - p2;
    return !sig((p1 ^ p2) / len) && sig(p1 % (p2 - p1)) >= 0;
}

std::vector <double> isCL(C c1, L l){ // 以离 l.p 近为序 
    double a = l.v.x, b = l.p.x - c1.o.x, c = l.v.y, d = l.p.y - c1.o.y;
    double e = sqr(a) + sqr(c), f = 2 * (a * b + c * d);
    double g = sqr(b) + sqr(d) - sqr(c1.r);
    double delta = sqr(f) - 4 * e * g;
    if (sig(delta) < 0) return {};
    if (!sig(delta)){
        return {-f / (2 * e)};
    }
    std::vector <double> ret;
    ret.push_back((-f - std::sqrt(delta)) / (2 * e));
    ret.push_back((-f + std::sqrt(delta)) / (2 * e));
    return ret;
}

// 重合:-1,内含:0,内切:1,相交:2,外切:3,相离:4 
std::pair <int, std::vector <P>> isCC(C c1, C c2){
    double d = (c1.o - c2.o).abs2();
    if (!sig(d)){
        if (!sig(c1.r - c2.r)){
            return {-1, {}};
        }
        return {0, {}};
    }
    if (sig(c1.r + c2.r - std::sqrt(d)) < 0) return {4, {}};
    if (sig(std::abs(c1.r - c2.r) - std::sqrt(d)) > 0) return {0, {}};
    double x = ((sqr(c1.r) - sqr(c2.r)) / d + 1) / 2;
    double y = std::max(sqr(c1.r) / d - sqr(x), 0.0);
    P q1 = c1.o + (c2.o - c1.o) * x;
    P q2 = ((c2.o - c1.o) * std::sqrt(y)).rot90(); 
    if (!sig(y)){
        return {!sig(c1.r + c2.r - std::sqrt(d)) ? 3 : 1, {q1}};
    }
    return {2, {q1 - q2, q1 + q2}};
}

int isCs(std::vector <C> &c, double mid){
    int n = c.size();
    double left = -INF, right = INF;
    for (int i = 0; i < n; ++ i){
        if (sig(mid - c[i].o.x - c[i].r) > 0) return 1;
        if (sig(c[i].o.x - c[i].r - mid) > 0) return 2;
        double delta = std::sqrt(std::max(0.0, sqr(c[i].r) - sqr(mid - c[i].o.x)));
        left = std::max(left, c[i].o.y - delta);
        right = std::min(right, c[i].o.y + delta);
        if (sig(left - right) > 0){
            for (int j = 0; j < i; ++ j){
                auto u = isCC(c[i], c[j]);
                auto ps = u.second;
                if (u.first <= 1) continue;
                if (u.first == 4) return 1;
                if (u.first == 3){
                    if (!sig(ps[0].x - mid)) continue;
                    return sig(ps[0].x - mid) < 0 ? 1 : 2;
                }
                if (!sig(ps[0].x - mid) || sig(ps[1].x - mid) != sig(ps[0].x - mid)) continue;
                return sig(ps[0].x - mid) < 0 ? 1 : 2;
            }
        }
    }
    return 0;
}

bool isCs(std::vector <C> &c){
    double right = -INF, left = INF;
    for (auto u : c){
        right = std::max(right, u.o.x + u.r);
        left = std::min(left, u.o.x - u.r);
    }
    for (int i = 0; i < 50; ++ i){
        double mid = (left + right) / 2;
        int x = isCs(c, mid);
        if (!x) return true;
        if (x == 1) right = mid;
        else left = mid;
    }
    return false;
}

double areaCC(C c1, C c2){
    double d = (c1.o - c2.o).abs();
    if (sig(c1.r + c2.r - d) <= 0){
        return 0;
    }
    if (sig(d - std::abs(c1.r - c2.r)) <= 0){
        return sqr(std::min(c1.r, c2.r)) * PI;
    }
    double x = (sqr(d) + sqr(c1.r) - sqr(c2.r)) / (2 * d);
    double t1 = std::acos(x / c1.r);
    double t2 = std::acos((d - x) / c2.r);
    return sqr(c1.r) * t1 + sqr(c2.r) * t2 - d * c1.r * sin(t1);
}

std::vector <P> tanCP(C c, P p){ // p在圆上时返回 p 点本身 
    double d = (p - c.o).abs2();
    double x = d - sqr(c.r);
    if (sig(x) < 0) return {};
    if (!sig(x)) return {p};
    P q1 = (p - c.o) * sqr(c.r) / d;
    P q2 = ((p - c.o) * -c.r * std::sqrt(x) / d).rot90();
    return {c.o + q1 - q2, c.o + q1 + q2};
}

std::vector <L> tanCC(C c1, C c2){
    std::vector <L> ret;
    if (!sig(c1.r - c2.r)){
        P dir = c2.o - c1.o;
        dir = (dir * c1.r / dir.abs()).rot90();
        ret.push_back(L (c1.o + dir, c2.o + dir));
        ret.push_back(L (c1.o - dir, c2.o - dir));
    }
    else{
        P p = (c1.o * -c2.r + c2.o * c1.r) / (c1.r - c2.r);
        std::vector <P> ps = tanCP(c1, p);
        std::vector <P> qs = tanCP(c2, p);
        for (int i = 0; i < ps.size() && i < qs.size(); ++ i){
            ret.push_back(L (ps[i], qs[i]));
        }
    }
    P p = (c1.o * c2.r + c2.o * c1.r) / (c1.r + c2.r);
    std::vector <P> ps = tanCP(c1, p);
    std::vector <P> qs = tanCP(c2, p);
    for (int i = 0; i < ps.size() && i < qs.size(); ++ i){
        ret.push_back(L (ps[i], qs[i]));
    }
    for (auto &u : ret){
        if (u.v == P (0, 0)){
            u.v = (u.p - c1.o).rot90();
        }
    }
    return ret;
}

C inC(P p1, P p2, P p3){
    double a = (p3 - p2).abs(), b = (p1 - p3).abs(), c = (p2 - p1).abs();
    P p = (p1 * a + p2 * b + p3 * c) / (a + b + c);
    return C (p, std::abs(disLP(L (p1, p2), p)));
}

C outC(P p1, P p2, P p3){
    P q1 = (p1 + p2) / 2, v1 = normal(p1 - p2);
    P q2 = (p2 + p3) / 2, v2 = normal(p2 - p3);
    L l1(q1, q1 + v1), l2(q2, q2 + v2);
    double t = isLL(l1, l2);
    P p = l1.point(t);
    return C (p, (p1 - p).abs());
}

// 内部:1, 外部:-1, 边上:0
int inPolygon(std::vector <P> &ps, P q){
    int n = ps.size();
    for (int i = 0; i < n; ++ i){
        if (onSeg(ps[i], ps[(i + 1) % n], q)){
            return 0;
        }
    }
    int ret = -1;
    for (int i = 0; i < n; ++ i){
        P a = ps[i], b = ps[(i + 1) % n];
        if (a.y > b.y) std::swap(a, b);
        if (sig((a - q) ^ (b - q)) < 0 && sig(a.y - q.y) < 0 && sig(b.y - q.y) >= 0){
            ret = -ret;
        }
    }
    return ret;
}

// >0表示 q 在 l 左边 
double onLeft(L l, P p){
    return l.v ^ (p - l.p);
}

std::vector <P> convexHull(std::vector <P> &ps){ //返回的凸包为逆时针方向
    const int N = 100010; // 抄时记得修改 
    static P stack[N];
    std::sort(ps.begin(), ps.end());
    int n = ps.size(), top = 0;
    for (int i = 0; i < n; ++ i){
        while (top > 1 && sig(onLeft(L (stack[top - 2], stack[top - 1]), ps[i])) <= 0){
            -- top;
        }
        stack[top ++] = ps[i];
    }
    int tmp = top;
    for (int i = n - 2; i >= 0; -- i){
        while (top > tmp && sig(onLeft(L (stack[top - 2], stack[top - 1]), ps[i])) <= 0){
            -- top;
        }
        stack[top ++] = ps[i];
    }
    if (n > 1) -- top;
    std::vector <P> ret;
    for (int i = 0; i < top; ++ i){
        ret.push_back(stack[i]);
    }
    return ret;
}

std::vector <P> minkSum(std::vector <P> &ps, std::vector <P> &qs){//O(n+m)
    std::vector <P> ret;
    int n = ps.size(), m = qs.size();
    P cur = ps[0] + qs[0];
    for (int i = 0, j = 0; i < n || j < m; ){
        if (i < n && (j == m || sig((ps[i + 1] - ps[i]) ^ (qs[j + 1] - qs[j])) >= 0)){
            cur = cur + ps[i + 1] - ps[i];
            ++ i;
        }
        else{
            cur = cur + qs[j + 1] - qs[j];
            ++ j;
        }
        ret.push_back(cur);
    }
    return ret;
}

bool inConvex(std::vector <P> &ps, P q){ //O(logn)
    int n = ps.size();
    if (sig(onLeft(L (ps[0], ps[1]), q)) < 0 || sig(onLeft(L (ps[0], ps[n - 1]), q) > 0)){
        return 0;
    }
    int left = 2, right = n - 1;
    while (left < right){
        int mid = left + right >> 1;
        if (sig(onLeft(L (ps[0], ps[mid]), q)) <= 0){
            right = mid;
        }
        else{
            left = mid + 1;
        }
    }
    return sig(onLeft(L (ps[right - 1], ps[right]), q)) >= 0;
}

int tanConPR(std::vector <P> &ps, P q){ //O(logn)
    int ret = 0, n = ps.size();
    int left = 1, right = n - 1;
    while (left <= right){
        bool dnl = onLeft(L (q, ps[left + 1]), ps[left]) > 0;
        int mid = left + right >> 1;
        bool dnm = onLeft(L (q, ps[mid + 1]), ps[mid]) > 0;
        if (dnm){
            if (onLeft(L (q, ps[ret]), ps[mid]) > 0){
                ret = mid;
            }
        }
        if (dnl){
            if (onLeft(L (q, ps[ret]), ps[left]) > 0){
                ret = left;
            }
            if (dnm && onLeft(L (q, ps[left]), ps[mid]) > 0){
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
        else{
            if (!dnm && onLeft(L (q, ps[left]), ps[mid]) > 0){
                left = mid + 1;
            }
            else{
                right = mid - 1;
            }
        }
    }
    return ret;
}

int tanConPL(std::vector <P> &ps, P q){
    int ret = 0, n = ps.size();
    int left = 1, right = n - 1;
    while (left <= right){
        bool dnl = onLeft(L (q, ps[left - 1]), ps[left]) < 0;
        int mid = left + right + 1 >> 1;
        bool dnm = onLeft(L (q, ps[mid - 1]), ps[mid]) < 0;
        if (dnm){
            if (onLeft(L (q, ps[ret]), ps[mid]) < 0){
                ret = mid;
            }
        }
        if (dnl){
            if (onLeft(L (q, ps[ret]), ps[left]) < 0){
                ret = left;
            }
            if (dnm && onLeft(L (q, ps[left]), ps[mid]) < 0){
                left = mid + 1;
            }
            else{
                right = mid - 1;
            }
        }
        else{
            if (!dnm && onLeft(L (q, ps[left]), ps[mid])){
                right = mid - 1;
            }
            else{
                left = mid + 1;
            }
        }
    }
    return ret;
}

std::vector <P> isConL(std::vector <P> &ps, P p, P q){//要求凸包为逆时针方向
    std::vector <double> arc;
    int n = ps.size();
    for (int i = 0; i < n; ++ i){
        ps.push_back(ps[i]);
    }
    ps.push_back(ps[0]);
    for (int i = 0; i < n; ++ i){
        arc.push_back(L (ps[i], ps[i + 1]).angle);
        if (i && arc[i] < arc[i - 1]){
            arc[i] += 2 * PI;
        }
    }
    auto getseg = [&ps](L l, int left, int right){
        -- left;
        while (left < right){
            int mid = left + right + 1 >> 1;
            if (sig(l.v ^ (ps[mid] - l.p)) < 0){
                left = mid;
            }
            else{
                right = mid - 1;
            }
        }
        return left;
    };
    if (q < p) std::swap(p, q);
    L l1(p, q), l2(q, p);
    double al = l1.angle;
    if (al < arc[0]) al += 2 * PI;
    int left = (std::lower_bound(arc.begin(), arc.end(), al) - arc.begin()) % n;
    double ar = l2.angle;
    if (ar < arc[0]) ar += 2 * PI;
    int right = std::lower_bound(arc.begin(), arc.end(), ar) - arc.begin();
    int down = getseg(l1, left, right);
    int up = getseg(l2, right, left + n);
    std::vector <P> ret;
    if (down >= left && up >= right){
        double t = isLL(l1, L (ps[down], ps[down + 1]));
        ret.push_back(l1.point(t));
        t = isLL(l2, L (ps[up], ps[up + 1]));
        ret.push_back(l2.point(t));
    }
    ps.erase(ps.begin() + n, ps.end());
    return ret;
}

std::vector <P> cutCon(std::vector <P> &ps, P p, P q){//用pq的左半平面切割ps,O(n)
    std::vector <P> ret;
    int n = ps.size();
    for (int i = 0; i < n; ++ i){
        P a = ps[i], b = ps[(i + 1) % n];
        if (sig((q - p) ^ (a - p)) >= 0){
            ret.push_back(a);
        }
        if (!sig((q - p) ^ (b - a))){
            double t = isLL(L (a, b), L (p, q));
            if (sig(t) > 0 && sig(t - 1) < 0){
                ret.push_back(a + (b - a) * t);
            }
        }
    }
    return ret;
}

std::vector <P> isHalfPlane(std::vector <L> &ls){
    std::sort(ls.begin(), ls.end());
    std::deque <L> dq;
    std::deque <P> ps;
    dq.push_back(ls[0]);
    int n = ls.size();
    auto isLLP = [](L l1, L l2){return l1.point(isLL(l1, l2));};
    for (int i = 1; i < n; ++ i){
        while (!ps.empty() && sig(onLeft(ls[i], ps.back())) <= 0) ps.pop_back(), dq.pop_back();
        while (!ps.empty() && sig(onLeft(ls[i], ps.front())) <= 0) ps.pop_front(), dq.pop_front();
        L l = dq.back();
        if (sig(ls[i].v ^ l.v)){
            dq.push_back(ls[i]);
            ps.push_back(isLLP(l, ls[i]));
        }
        else{
            if (sig(onLeft(l, ls[i].p)) > 0){
                dq.pop_back();
                if (!dq.empty()){
                    ps.pop_back();
                    ps.push_back(isLLP(dq.back(), ls[i]));
                }
                dq.push_back(ls[i]);
            }
        }
    }
    while (!ps.empty() && sig(onLeft(dq.front(), ps.back())) <= 0) ps.pop_back(), dq.pop_back();
    if (dq.size() <= 2) return {};
    ps.push_back(isLLP(dq.front(), dq.back()));
    std::vector <P> ret;
    while (!ps.empty()){
        ret.push_back(ps.front());
        ps.pop_front();
    }
    return ret;
}

double areaCPol(C c, std::vector <P> &ps){
    auto area = [c](P p, P q){
        double theta = (p - c.o).angle() - (q - c.o).angle();
        if (theta < 0) theta += PI * 2;
        if (theta >= 2 * PI) theta -= PI * 2;
        theta = std::min(theta, 2 * PI - theta);
        return sqr(c.r) * theta;
    };
    double ret = 0;
    int n = ps.size();
    for (int i = 0; i < n; ++ i){
        P p1 = ps[i], p2 = ps[(i + 1) % n];
        L l(p1, p2);
        std::vector <double> vec = isCL(c, l);
        double tmp = 0;
        bool flag1 = sig((p1 - c.o).abs2() - sqr(c.r)) <= 0, flag2 = sig((p2 - c.o).abs2() - sqr(c.r)) <= 0;
        if (flag1 && flag2){
            tmp = std::abs((p1 - c.o) ^ (p2 - c.o));
        }
        else if (flag1 || flag2){
            if (!flag1){
                P p = l.point(vec[0]);
                tmp = area(p1, p) + std::abs((p - c.o) ^ (p2 - c.o));
            }
            else{
                P p = l.point(*(-- vec.end()));
                tmp = area(p, p2) + std::abs((p1 - c.o) ^ (p - c.o));
            }
        }
        else{
            if (vec.size() == 2 && sig(vec[0]) > 0 && sig(vec[0] - 1) < 0){
                P p3 = l.point(vec[0]), p4 = l.point(vec[1]);
                tmp = area(p1, p3) + area(p4, p2) + std::abs((p3 - c.o) ^ (p4 - c.o));
            }
            else{
                tmp = area(p1, p2);
            }
        }
        ret += tmp * sig((p1 - c.o) ^ (p2 - c.o));
    }
    return std::abs(ret) / 2;
}

std::pair <double, P> areaCs(std::vector <C> &cs){ // 圆并面积,重心,被卡时间时可预先去掉被其它圆包含的圆
    double ret = 0;
    P pret;
    int n = cs.size();
    for (int i = 0; i < n; ++ i){
        std::vector <std::pair <double, int>> vec = {{0, 0}, {PI * 2, 0}};
        int cnt = 1;
        for (int j = 0; j < n; ++ j){
            double dis = (cs[i].o - cs[j].o).abs();
            if (!sig(dis) && !sig(cs[i].r - cs[j].r)){
                if (i < j){
                    ++ cnt;
                }
                continue;
            }
            if (sig(dis - cs[j].r - cs[i].r) >= 0 || sig(dis + cs[j].r - cs[i].r) <= 0){
                continue;
            }
            if (sig(dis + cs[i].r - cs[j].r) <= 0){
                ++ cnt;
                continue;
            }
            double angle = L (cs[i].o, cs[j].o).angle;
            double p = (sqr(cs[i].r) + sqr(dis) - sqr(cs[j].r)) / (2 * cs[i].r * dis);
            p = std::acos(std::max(-1.0, std::min(1.0, p)));
            double left = angle - p, right = angle + p;
            if (left < 0) left += PI * 2;
            if (right < 0) right += PI * 2;
            if (left >= 2 * PI) left -= PI * 2;
            if (right >= 2 * PI) right -= PI * 2;
            vec.push_back({left, 1});
            vec.push_back({right, -1});
            if (left >= right){
                ++ cnt;
            }
        }
        std::sort(vec.begin(), vec.end());
        for (int j = 0, sz = vec.size(); j + 1 < sz; ++ j){
            cnt += vec[j].second;
            if (cnt == 1){
                double delta = vec[j + 1].first - vec[j].first;
                if (sig(delta) <= 0) continue;
                double sin = std::sin(delta / 2);
                P cen (4 * cs[i].r * sin * sin * sin / (3 * (delta - std::sin(delta))), 0);
                cen = cen.rot((vec[j].first + vec[j + 1].first) / 2) + cs[i].o;
                double area = sqr(cs[i].r) * (delta - std::sin(delta));
                pret = pret + cen * area;
                ret += area;
                P p1 = cs[i].point(vec[j].first), p2 = cs[i].point(vec[j + 1].first);
                area = p1 ^ p2;
                pret = pret + (p1 + p2) * area / 3;
                ret += area;
            }
        }
    }
    return {ret / 2, pret / ret};
}

double areaisCs(std::vector <C> &ccs){
    std::vector <C> cs;
    for (int i = 0, sz = ccs.size(); i < sz; ++ i){
        bool flag = true;
        for (int j = 0; j < sz; ++ j){
            if (i == j) continue;
            double dis = (ccs[i].o - ccs[j].o).abs();
            if (sig(dis - ccs[i].r - ccs[j].r) >= 0) return 0.0;
            if (!sig(dis) && !sig(ccs[i].r - ccs[j].r)){
                if (i < j){
                    flag = false;
                    break;
                }
            }
            else{
                if (sig(dis + ccs[i].r - ccs[j].r) <= 0){
                    flag = false;
                    break;
                }
            }
        }
        if (flag) cs.push_back(ccs[i]);
    }
    int n = cs.size();
    typedef std::pair <double, double> pdd;
    auto inter = [](const pdd &p1, const pdd &p2, std::vector <pdd> &vec){
        pdd p = {std::max(p1.first, p2.first), std::min(p1.second, p2.second)};
        if (p.first <= p.second) vec.push_back(p);
    };
    double ret = 0;
    for (int i = 0; i < n; ++ i){
        std::vector <pdd> vec = {{0, 2 * PI}};
        for (int j = 0; j < n; ++ j){
            double angle = L (cs[i].o, cs[j].o).angle;
            double dis = (cs[i].o - cs[j].o).abs();
            double p = (sqr(cs[i].r) + sqr(dis) - sqr(cs[j].r)) / (2 * cs[i].r * dis);
            p = std::acos(std::max(-1.0, std::min(1.0, p)));
            double left = angle - p, right = angle + p;
            if (left < 0) left += PI * 2;
            if (right < 0) right += PI * 2;
            if (left >= 2 * PI) left -= PI * 2;
            if (right >= 2 * PI) right -= PI * 2;
            std::vector <pdd> tmp;
            for (auto u : vec){
                if (left >= right){
                    inter({left, 2 * PI}, u, tmp);
                    inter({0, right}, u, tmp);
                }
                else{
                    inter({left, right}, u, tmp);
                }
            }
            vec = tmp;
        }
        for (auto u : vec){
            P p1 = cs[i].point(u.first), p2 = cs[i].point(u.second);
            double delta = u.second - u.first;
            ret += sqr(cs[i].r) * (delta - std::sin(delta));
            ret += p1 ^ p2;
        }
    }
    return ret / 2;
}

// 求点到凸多边形 ps 的距离,ps必须是逆时针的,p必须在ps外部
double disConvexP(std::vector <P> &ps, P q){
    int n = ps.size();
    int left = 0, right = n;
    auto pin = [](P p1, P p2, P q){
        return sig(p1 ^ q) >= 0 && sig(p2 ^ q) <= 0;
    };
    auto in = [pin](P p1, P p2, P p3, P p4, P q){
        P o12 = (p1 - p2).rot90();
        P o23 = (p2 - p3).rot90();
        P o34 = (p3 - p4).rot90();
        return pin(o12, o23, q - p2) || pin(o23, o34, q - p3)
                || pin(o23, p3 - p2, q - p2) && pin(p2 - p3, o23, q - p3);
    };
    while (right - left > 1){
        int mid = left + right >> 1;
        if (in(ps[(left + n - 1) % n], ps[left], ps[mid], ps[(mid + 1) % n], q)){
            right = mid;
        }
        else{
            left = mid;
        }
    }
    return disSP(ps[left], ps[right % n], q);
}

// 求凸多边形 ps 的直径 
double convexDiameter(std::vector <P> &ps){
    int n = ps.size();
    int is = 0, js = 0;
    for (int i = 1; i < n; ++ i){
        if (ps[i].x > ps[is].x){
            is = i;
        }
        if (ps[i].x < ps[js].x){
            js = i;
        }
    }
    double maxd = (ps[is] - ps[js]).abs();
    int i = is, j = js;
    do{
        if (sig((ps[(i + 1) % n] - ps[i]) ^ (ps[(j + 1) % n] - ps[j])) >= 0){
            j = (j + 1) % n;
        }
        else{
            i = (i + 1) % n;
        }
        maxd = std::max(maxd, (ps[i] - ps[j]).abs());
    }
    while (i != is || j != js);
    return maxd;
}

// 求 ps 中的点的最小包围圆 
C minCoverC(std::vector <P> &ps){
    int n = ps.size();
    std::random_shuffle(ps.begin(), ps.end());
    C ret(ps[0], 0);
    for (int i = 1; i < n; ++ i){
        if (sig((ps[i] - ret.o).abs() - ret.r) > 0){
            ret = C (ps[i], 0);
            for (int j = 0; j < i; ++ j){
                if (sig((ps[j] - ret.o).abs() - ret.r) > 0){
                    ret = C ((ps[i] + ps[j]) / 2, (ps[i] - ps[j]).abs() / 2);
                    for (int k = 0; k < j; ++ k){
                        if (sig((ps[k] - ret.o).abs() - ret.r) > 0){
                            ret = outC(ps[i], ps[j], ps[k]);
                        }
                    }
                }
            }
        }
    }
    return ret;
}

/*
void work() {
    scanf("%d" , &n);
    for (int i = 0 ; i < n ; ++ i) {
        L[i].input();
        P[i] = L[i];
    }
    int m = n;
    for (int i = 0 ; i + 1 < n ; ++ i)        
        for (int j = i + 1 ; j + 1 < n ; ++ j) {
            if (dcmp((P[i + 1] - P[i]) ^ (P[j + 1] - P[j])) != 0)
                P[m ++] = GetLineIntersection(P[i] , P[i + 1] - P[i] , P[j] , P[j + 1] - P[j]);
        }
    sort(P , P + m);
    m = unique(P , P + m) - P;
    memset(pre , -1 , sizeof(pre));
    set< pair<int , int> > Hash;
    for (int i = 0 ; i + 1 < n ; ++ i) {
        vector< pair <Point , int> > V;
        for (int j = 0 ; j < m ; ++ j)
            if (OnSegment(P[j] , L[i] , L[i + 1]))
                V.push_back(make_pair(P[j] , j));
        sort(V.begin() , V.end());
        for (int j = 0 ; j + 1 < V.size() ; ++ j) {
            int x = V[j].second , y = V[j + 1].second; 
            if (!Hash.count(make_pair(x , y))) {
                Hash.insert(make_pair(x , y));
                e[mcnt] = (edge) {y , pre[x]} , pre[x] = mcnt ++;
            }
            if (!Hash.count(make_pair(y , x))) {
                Hash.insert(make_pair(y , x));
                e[mcnt] = (edge) {x , pre[y]} , pre[y] = mcnt ++;
            }
        }
    }
    for (int x = 0 ; x < m ; ++ x) {
        vector< pair<double , int> > V;
        for (int i = pre[x] ; ~i ; i = e[i].next) {
            int y = e[i].x;
            V.push_back(make_pair((P[y] - P[x]).arg() , i));
        }
        sort(V.begin() , V.end());
        for (int i = 0 ; i < V.size() ; ++ i) {
            int j = (i + 1) % V.size();
            Next[V[j].second ^ 1] = V[i].second;
        }
    }
    double res = 0;
    for (int i = 0 ; i < mcnt ; ++ i) {
        if (!vis[i]) {
            int x = i;
            double area = 0;
            while (!vis[x]) {
                vis[x] = 1;
                area += (P[e[x ^ 1].x] ^ P[e[x].x]);
                x = Next[x];
            }
            if (x == i && dcmp(area) > 0)
                res += area;
        }
    }
    printf("%.8f\n" , res / 2);
}
*/

int main(){
    srand((unsigned) time(NULL)); 
    return 0;
}