QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#813679#7027. Machining Disc RotorsyangjlAC ✓175ms3916kbC++2014.4kb2024-12-14 11:44:462024-12-14 11:44:47

Judging History

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

  • [2024-12-14 11:44:47]
  • 评测
  • 测评结果:AC
  • 用时:175ms
  • 内存:3916kb
  • [2024-12-14 11:44:46]
  • 提交

answer

/**
 *    author:  yangjl
 *    created: 2024.12.14 11:26:07
**/
#include <bits/stdc++.h>
#ifdef YJL
#include "debug.h"
#else
#define debug(...)0
#endif
using namespace std;
using ll = long long;

template<class T>
istream& operator>>(istream& is, vector<T>& v) {
    for(auto& x : v) {
        is >> x;
    }
    return is;
}
template<class T>
int sgn(const T& v) {
    static constexpr T eps = 1e-8;
    return v > eps ? 1 : v < -eps ? -1 : 0;
}
template<class T>
struct Point {// Point or Vector
    T x, y;
    Point() : x(0), y(0) {}
    Point(T x, T y) : x(x), y(y) {}
    template<class U>
    explicit operator Point<U>() const {
        return Point<U>(U(x), U(y));
    }
    Point operator+(const Point& o) const {
        return Point(x + o.x, y + o.y);
    }
    Point operator-(const Point& o) const {
        return Point(x - o.x, y - o.y);
    }
    Point operator-() const {
        return Point(-x, -y);
    }
    Point operator*(const T& v) const {
        return Point(x * v, y * v);
    }
    friend Point operator*(const T& v, const Point<T>& o) {
        return Point(o.x * v, o.y * v);
    }
    Point operator/(const T& v) const {
        return Point(x / v, y / v);
    }
    Point operator+=(const Point& o) {
        x += o.x, y += o.y;
        return *this;
    }
    Point operator-=(const Point& o) {
        x -= o.x, y -= o.y;
        return *this;
    }
    Point operator*=(const T& v) {
        x *= v, y *= v;
        return *this;
    }
    Point operator/=(const T& v) {
        x /= v, y /= v;
        return *this;
    }
    bool operator==(const Point& o) const {
        return sgn(x - o.x) == 0 and sgn(y - o.y) == 0;
    }
    bool operator!=(const Point& o) const {
        return sgn(x - o.x) != 0 or sgn(y - o.y) != 0;
    }
    bool operator<(const Point& o) const {
        return sgn(x - o.x) < 0 or sgn(x - o.x) == 0 and sgn(y - o.y) < 0;
    }
    bool operator>(const Point& o) const {
        return sgn(x - o.x) > 0 or sgn(x - o.x) == 0 and sgn(y - o.y) > 0;
    }
    static bool argcmp(const Point& a, const Point& b) {
        static auto get = [&](const Point& o) {
            if(sgn(o.x) == 0 and sgn(o.y) == 0) return 0;
            if(sgn(o.y) > 0 or sgn(o.y) == 0 and sgn(o.x) < 0) return 1;
            return -1;
        };
        int ta = get(a), tb = get(b);
        if(ta != tb) return ta < tb;
        return a.toLeft(b) == 1;// 不关注极径
        // int tole = a.toLeft(b);
        // if(tole != 0) return tole == 1;
        // return sgn(a.square()-b.square()) < 0;// 极角相同按极径排
    }
    T dot(const Point& o) const {
        return x * o.x + y * o.y;
    }
    T cross(const Point& o) const {
        return x * o.y - y * o.x;
    }
    int toLeft(const Point& o) const {
        return sgn(cross(o));
    }
    T square() const {
        return x * x + y * y;
    }
    T interSquare(const Point& o) const {
        return (*this - o).square();
    }
    friend istream& operator>>(istream& in, Point& o) {
        return in >> o.x >> o.y;
    }
    friend ostream& operator<<(ostream& out, Point const& o) {
        return out << "(" << o.x << "," << o.y << ")";
    }
    // 涉及浮点数
    double length() const {
        return sqrtl(square());
    }
    double distance(const Point& o) const {
        return (*this - o).length();
    }
    // 逆时针旋转 rad, rotate90(0, 1);
    Point<T> rotate(T cosr, T sinr) const {
        return Point(x * cosr - y * sinr, x * sinr + y * cosr);
    }
    // 两向量夹角范围是 [0,PI]
    double ang(const Point& o) const {
        return acosl(max<double>(-1.L, min<double>(1.L, dot(o) / (length() * o.length()))));
    }
};
template<class T>
struct Line {// 直线,线段,射线
    Point<T> a, b;// 方向为 a->b
    Line() {}
    Line(const Point<T>& a, const Point<T>& b) : a(a), b(b) {}
    template<class U>
    Line(const Point<U>& a, const Point<U>& b) : a(a), b(b) {}
    Point<T> vec() const {
        return b - a;
    }
    // Line ----------------------------------------------------------
    bool parallel(const Line& l) const {
        return sgn((b - a).cross(l.b - l.a)) == 0;
    }
    int toLeft(const Point<T>& o) const {
        return (b - a).toLeft(o - a);
    }
    // 涉及浮点数
    // 直线交点
    Point<double> lineIntersection(const Line& l) const {
        return Point<double>(a) + Point<double>(b - a) *
            (1. * (l.b - l.a).cross(a - l.a) / (l.b - l.a).cross(a - b));
    }
    // 点到直线的距离
    double distanceLP(const Point<T>& o) const {
        return abs((a - b).cross(a - o)) / (a - b).length();
    }
    // 点在直线上的投影
    Point<double> projection(const Point<T>& o) const {
        auto t = 1.L * vec().dot(o - a) / vec().square();
        return Point<double>(a) + Point<double>(vec()) * t;
    }
    // -1 点在线段端点 | 0 点不在线段上 | 1 点严格在线段上
    int contain(const Point<T>& o) const {
        if(o == a or o == b) return -1;
        return (o - a).toLeft(o - b) == 0 and sgn((o - a).dot(o - b)) < 0;
    }
    // 判断线段 vs 直线
    // 0 不相交 | 1 严格相交 | 2 仅在某一线段端点处相交 | 3 直线包含线段
    int segmentCrossLine(const Line& l) const {
        int num = !l.toLeft(a) + !l.toLeft(b);
        if(num) return num + 1;
        return l.toLeft(a) != l.toLeft(b);
    }
    // 判断线段 vs 线段
    // 0 不相交 | 1 严格相交 | 2 仅在某一线段端点处相交 | 3 两线段有重叠
    int segmentCrossSegment(Line s) const {
        if((a < b) != (s.a < s.b))
            swap(s.a, s.b);
        int num = (contain(s.a) != 0) + (contain(s.b) != 0)
            + (s.contain(a) != 0) + (s.contain(b) != 0);
        if(parallel(s)) {
            if(!num) return 0;
            if(b == s.a or a == s.b) return 2;// -.-
            return 3;
        }
        if(num) return 2;
        return toLeft(s.a) * toLeft(s.b) == -1 and s.toLeft(a) * s.toLeft(b) == -1;
    }
    // 射线 vs 线段 判断相交
    // 0 不相交 | 1 严格相交 | 2 某个端点相交
    int raysCrossSegment(Line const& seg) const {
        if(seg.contain(a)) return 2;
        if(toLeft(seg.a) == 0 and vec().dot(seg.a - a) > 0) return 2;
        if(toLeft(seg.b) == 0 and vec().dot(seg.b - a) > 0) return 2;
        return toLeft(seg.a) != toLeft(seg.b) and seg.toLeft(a) != seg.vec().toLeft(vec());
    }
    // 点到线段的距离
    double distanceSP(const Point<T>& o) const {
        if(sgn((o - a).dot(b - a)) < 0) return o.distance(a);
        if(sgn((o - b).dot(a - b)) < 0) return o.distance(b);
        return abs((a - b).cross(a - o)) / (a - b).length();
    }
    // 两线段间距离
    double distanceSS(const Line& s) const {
        if(segmentCrossSegment(s)) return 0;
        return min({distanceSP(s.a),distanceSP(s.b),
                s.distanceSP(a),s.distanceSP(b)});
    }
    // 直线向左/右偏移 r 的距离
    Line<T> offset(int tolef, T r) {
        Point<T> v(vec().rotate(0, tolef == 1 ? 1 : -1));
        v = v * r / v.length();
        return Line<T>(a + v, b + v);
    }
};
constexpr double PI = 3.1415926535897932384L;
// using D = double;
template<class D>
struct Circle {
    Point<D> c;
    D r;
    Circle() : c(), r() {}
    Circle(Point<D> const& _c, D _r) : c(_c), r(_r) {}
    Circle(D _x, D _y, D _r) : c(_x, _y), r(_r) {}
    bool operator==(Circle const& cir) const {
        return c == cir.c && sgn(r - cir.r) == 0;
    }
    double perimeter() const {// 周长
        return 2 * PI * r;
    }
    double area() const {// 面积
        return PI * r * r;
    }
    // -1 圆内 | 0 圆上 | 1 圆外
    template<class I>
    int relation(Point<I> const& p) const {
        return sgn(c.interSquare(p) - r * r);
    }
    // -1 相交 | 0 相切 | 1 相离
    template<class I>
    int relation(Line<I> const& l) const {
        if constexpr(!is_same_v<D, double> && !is_same_v<I, double>) {// x,y int <=1e9
            __int128_t t = l.vec().cross(c - l.a);
            return sgn(t * t - (__int128_t)r * r * l.vec().square());
        }
        return sgn(l.distanceLP(c) - r);
    }
    // 0 相同 | 1 相交 | 2 外切 | 3 相离 | 4 内含 | 5 内切
    int relation(Circle const& cir) const {
        if(*this == cir) return 0;
        auto squre = c.interSquare(cir.c), sr = r + cir.r, dr = abs(r - cir.r);
        if(sgn(squre - sr * sr) > 0) return 3;
        if(sgn(squre - sr * sr) == 0) return 2;
        if(sgn(squre - dr * dr) < 0) return 4;
        if(sgn(squre - dr * dr) == 0) return 5;
        return 1;
    }
    friend istream& operator>>(istream& in, Circle& cir) {
        return in >> cir.c >> cir.r;
    }
    friend ostream& operator<<(ostream& out, Circle const& cir) {
        return out << "(" << cir.c.x << "," << cir.c.y << "," << cir.r << ")";
    }
    // 涉及浮点数
    vector<Point<double>> intersection(Line<double> const& l) const {
        Point<double> cp = l.projection(c);
        int t = relation(l);
        if(t == 1) return {};
        if(t == 0) return {cp};
        double d = l.distanceLP(c);
        double k = sqrtl(r * r - d * d);
        Point<double> e = l.vec() / l.vec().length();
        return {cp - e * k, cp + e * k};
    }
    vector<Point<double>> intersection(Circle const& cir) const {
        int re = relation(cir);
        assert(re != 0);// 相同,无数个交点
        if(re == 3 || re == 4) return {};
        Point<double> v = (cir.c - c) / c.distance(cir.c) * r;
        if(re == 2) return {c + v};
        if(re == 5) return {c + v * (r > cir.r ? 1.L : -1.L)};
        auto d2 = c.interSquare(cir.c);
        double cosa = (r * r + d2 - cir.r * cir.r) / (2.L * r * sqrtl(d2));
        double sina = sqrtl(1 - cosa * cosa);
        return {c + v.rotate(cosa, -sina), c + v.rotate(cosa, sina)};
    }
    double bowArea(Point<double> const& s, Point<double> const& t) const {// s->t弓形面积
        double cros = (t - s).cross(c - s);
        if(sgn(cros) < 0) return area() - bowArea(t, s);
        return (s.ang(t) / PI * area() - cros) / 2;
    }
    double crossArea(Circle const& cir) const {// 圆与圆交集
        int re = relation(cir);
        if(re == 2 || re == 3) return 0;
        if(re != 1) return min(area(), cir.area());
        auto cs = intersection(cir);
        return bowArea(cs[1], cs[0]) + cir.bowArea(cs[0], cs[1]);
    }
    vector<Line<D>> tangentLine(Point<D> const& p) const {
        int re = relation(p);
        if(re == -1) return {};
        if(re == 0) return {Line<double>(p, p + (p - c).rotate(0, 1))};
        double d = c.distance(p), cosa = r / d, sina = sqrtl(1 - cosa * cosa);
        Point<double> v = (p - c) / d * r;
        return {Line(p, c + v.rotate(cosa, sina)), Line(p, c + v.rotate(cosa, -sina))};
    }
    vector<Line<double>> commonTangentLine(Circle const& cir) const {
        int re = relation(cir);
        assert(re != 0);// 相同,无数公切线
        if(re == 4) return {};
        vector<Line<double>> lines;
        if(re == 2 || re == 5) {
            Point<double> p = intersection(cir)[0];
            lines.emplace_back(p, p + (c - cir.c).rotate(0, 1));
        }
        double d = c.distance(cir.c);
        Point<double> e = (cir.c - c) / d;
        if(re == 1 || re == 2) {
            double cosa = (r - cir.r) / d, sina = sqrtl(1 - cosa * cosa);
            Point<double> e1 = e.rotate(cosa, -sina), e2 = e.rotate(cosa, sina);
            lines.emplace_back(c + e1 * r, c + e2 * r);
            lines.emplace_back(cir.c + e1 * cir.r, cir.c + e2 * cir.r);
        }
        if(re == 3) {
            double cosa = (r + cir.r) / d, sina = sqrtl(1 - cosa * cosa);
            Point<double> e1 = e.rotate(cosa, -sina), e2 = e.rotate(cosa, sina);
            lines.emplace_back(c + e1 * r, c + e2 * r);
            lines.emplace_back(cir.c - e1 * cir.r, cir.c - e2 * cir.r);
        }
        return lines;
    }
    tuple<int, Circle, Line<double>> inverse(Line<double> const& l) const {
        int t = l.toLeft(c);
        if(t == 0) return make_tuple(1, Circle(), l);
        Point<double> v = l.vec().rotate(0, (t == 1 ? -1 : 1));
        double d = r * r / l.distanceLP(c);
        return make_tuple(0, Circle(c + v / v.length() * d / 2, d / 2), Line<double>());
    }
    tuple<int, Circle, Line<double>> inverse(Circle const& cir) const {
        double d = cir.c.distance(c);
        Point<double> e = (cir.c - c) / d;
        if(cir.relation(c) == 0) {
            double d = r * r / (2 * cir.r);
            Point<double> p = c + e * d;
            return make_tuple(1, Circle(), Line<double>(p, p + e.rotate(0, 1)));
        }
        if(c == cir.c) return make_tuple(0, Circle(c, r * r / cir.r, Line<double>()));
        Point<double> p = c + (r * r / (d - cir.r)) * e;
        Point<double> q = c + (r * r / (d + cir.r)) * e;
        return make_tuple(0, Circle((p + q) / 2, p.distance(q) / 2), Line<double>());
    }
};

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cout << fixed << setprecision(15);
    int tt;
    cin >> tt;
    for(int casei = 1; casei <= tt; ++casei) {
        int n, R;
        cin >> n >> R;
        Circle<double> mainC(0, 0, R);
        vector<Circle<double>> cirs;
        vector<Point<double>> cros, ps;
        for(int i = 0; i < n; ++i) {
            Circle<double> c;
            cin >> c;
            int re = mainC.relation(c);
            if(re == 1) {
                cirs.emplace_back(c);
                auto cs = mainC.intersection(c);
                cros.insert(cros.end(), cs.begin(), cs.end());
            }
        }

        auto isNotCover = [&](Point<double> p) {
            for(auto& cir : cirs) {
                if(cir.relation(p) == -1) {
                    return false;
                }
            }
            return true;
        };

        for(auto& p : cros) {
            if(isNotCover(p)) {
                ps.emplace_back(p);
            }
        }

        n = ps.size();
        double d = 0;
        for(int i = 0; i < n; ++i) {
            if(isNotCover(mainC.c * 2 - ps[i])) {
                d = 2 * R;
                break;
            }
            for(int j = i + 1; j < n; ++j) {
                d = max(d, ps[i].distance(ps[j]));
            }
        }

        cout << "Case #" << casei << ": " << d << "\n";
    }
    return 0;
}
/*


*/

这程序好像有点Bug,我给组数据试试?

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

1
3 10
0 12 10
11 -6 10
-11 -6 10

output:

Case #1: 18.611654895000253

result:

ok 1 cases

Test #2:

score: 0
Accepted
time: 66ms
memory: 3916kb

input:

5000
3 1000
750 500 625
-250 -625 625
-1000 1000 1000
3 8
-6 -4 5
2 5 5
8 -8 8
1 710
426 -568 994
1 10
-8 6 15
14 931
622 -651 207
-930 438 552
931 890 743
-264 -923 671
889 -315 179
15 761 173
-440 883 81
-938 -310 170
-271 981 91
918 -88 47
136 927 26
903 29 61
-162 936 22
917 129 18
32 595
431 11...

output:

Case #1: 1998.628237512162968
Case #2: 15.989025900097303
Case #3: 1420.000000000000000
Case #4: 19.843134832984433
Case #5: 1862.000000000000000
Case #6: 1190.000000000000000
Case #7: 934.000000000000000
Case #8: 542.000000000000000
Case #9: 1808.000000000000000
Case #10: 1472.000000000000000
Case ...

result:

ok 5000 cases

Test #3:

score: 0
Accepted
time: 175ms
memory: 3916kb

input:

5000
48 527
-419 -335 761
519 85 1
-47 524 3
301 431 2
489 -193 3
-102 516 2
-69 521 2
526 2 3
68 522 3
507 139 1
490 191 1
514 109 2
388 355 2
203 485 2
-127 510 3
42 524 1
323 414 1
11 526 1
-17 526 3
452 269 3
514 -111 3
94 517 1
525 -27 1
347 396 1
480 215 3
275 447 2
150 504 3
226 475 1
465 -24...

output:

Case #1: 1053.694800690881038
Case #2: 1269.660021675118514
Case #3: 1143.844334818409834
Case #4: 1183.562268928594449
Case #5: 1304.000000000000000
Case #6: 1173.961249922394927
Case #7: 1051.608339700099577
Case #8: 1027.719369369270680
Case #9: 1314.000000000000000
Case #10: 1007.717091814115065...

result:

ok 5000 cases