1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
| #include<bits/stdc++.h> using namespace std; #define endl '\n' #define FL(a,b,c) for(int a=(b),a##end=(c);a<=a##end;++a) #define FR(a,b,c) for(int a=(b),a##end=(c);a>=a##end;--a) #define lowbit(x) ((x)&-(x)) #define eb emplace_back #define sz(x) (int)((x).size()) #define int long long #define vt vector #define fr first #define se second bool IOS=(cin.tie(0)->sync_with_stdio(0),0);
#ifdef LOCAL bool IOS1=(freopen(LOCAL".in", "r", stdin),1); bool IOS2=(freopen(LOCAL".out", "w", stdout),1); #endif #define mmt(x, y) memset(x, y, sizeof x) #define PII pair<int, int> #define max(a, b)({auto f7r=(a);auto j3h=(b);f7r<j3h?j3h:f7r;}) #define cmax(a, b)({auto j3h=(b);(j3h>a)&&(a=j3h);}) #define min(a, b)({auto f7r=(a);auto j3h=(b);f7r>j3h?j3h:f7r;}) #define cmin(a, b)({auto j3h=(b);(j3h<a)&&(a=j3h);}) constexpr int N = 1e6 + 10; namespace cg{ typedef long double Ld; const Ld eps = 1e-9; const Ld PI = 3.1415926535897932626;
inline bool is_zero(Ld x){return fabs(x) < eps;} inline bool eq(Ld x, Ld y){return is_zero(x - y);} inline bool lt(Ld x, Ld y){return !eq(x, y) && x < y;} inline bool gt(Ld x, Ld y){return !eq(x, y) && x > y;}
struct Vec{ Ld x, y; Vec():x(0), y(0){} Vec(Ld x, Ld y):x(x), y(y){} inline Ld length()const{return sqrt(x * x + y * y);} inline Ld ang()const{return atan2(y, x);} inline Vec resize(Ld len)const{ if(*this)return len /= length(), Vec(x * len, y * len); else return Vec(); } Vec operator+(const Vec V)const{return Vec(x + V.x, y + V.y);} Vec operator-()const{return Vec(-x, -y);} Vec operator-(const Vec V)const{return *this + (-V);} Vec operator*(const Ld a)const{return Vec(x * a, y * a);} friend Vec operator*(const Ld a,const Vec v){return v * a;} Vec operator/(const Ld a)const{return Vec(x / a, y / a);} operator bool()const{return !(is_zero(x) && is_zero(y));} bool operator==(const Vec V)const{return!bool(*this - V);} bool operator!=(const Vec V)const{return bool(*this - V);} bool operator<(const Vec V)const{return eq(x, V.x) ? lt(y, V.y) : lt(x, V.x);} bool operator>(const Vec V)const{return eq(x, V.x) ? gt(y, V.y) : gt(x, V.x);} Vec cw_r90(){return Vec(y, -x);} }; typedef Vec Pt;
inline Ld dst(Pt a, Pt b){return (b - a).length();} struct Cir{ Pt o;Ld r; Cir(){r = 0;} Cir(Pt _o, Ld _r):o(_o), r(_r){} };
int cir_inter_kind(Cir a, Cir b){ Ld d = dst(a.o, b.o); if(gt(d, a.r + b.r))return 4; if(eq(d, a.r + b.r))return 3; if(gt(d, fabsl(a.r - b.r)))return 2; if(eq(d, fabsl(a.r - b.r)))return 1; return 0; }
pair<Ld, Ld> cir_inter_Ld(Cir c1, Cir c2){ Vec oo = c2.o - c1.o; Ld d = oo.length(), p = oo.ang(), D = (c1.r * c1.r + d * d - c2.r * c2.r), b1, b2; D = acosl(D / (2 * c1.r * d)), b1 = p + D, b2 = p - D; (b1 >= 2 * PI) && (b1 -= 2 * PI), (b2 < 0) && (b2 += 2 * PI); (b1 < 0) && (b1 += 2 * PI), (b2 >= 2 * PI) && (b2 -= 2 * PI); return make_pair(b1, b2); }
Ld cir_seg_area(Ld r, Ld angle){return r * r * (angle - sinl(angle)) / Ld(2);}
vt<Cir> cir_clear_coincide(vt<Cir>g){ vt<Cir>w;sort(g.begin(), g.end(), [](Cir&a, Cir&b){return a.r > b.r;}); FL(i, 0, sz(g) - 1){ bool flag = 1; for(auto&k : w)if(cir_inter_kind(g[i], k) <= 1){flag = 0;break;} if(flag)w.push_back(g[i]); } return w; }
Pt cir_rotate_ang(Cir a, Ld ang){return a.o + Vec(cosl(ang) * a.r, sinl(ang) * a.r);} struct arcs{ Cir o;bool s;Ld l, r; arcs():o(), s(), l(), r() {} arcs(const Cir o, bool s, Ld l, Ld r):o(o), s(s), l(l), r(r){} Ld get(Ld x){return x -= o.o.x, x = sqrtl(fabsl(o.r * o.r - x * x)), o.o.y + (s ? x : -x);} Ld ang(){ Ld x1 = (l - o.o.x) / o.r, x2 = (r - o.o.x) / o.r, r1, r2; cmax(x1, -1), cmin(x1, 1), cmax(x2, -1), cmin(x2, 1); return r1 = acos(x1), r2 = acosl(x2), fabsl(r1 - r2); } };
Ld cir_inter_area(vt<Cir>g){ vt<Cir>w = cir_clear_coincide(g);vt<Ld>imp;vt<arcs>arc; FL(i, 0, sz(w) - 1){ vt<pair<Ld, int>>d;int c = 0;d.eb(PI / 2, 0), d.eb(PI * 3 / 2, 0); FL(j, 0, sz(w) - 1)if(i != j && cir_inter_kind(w[i], w[j]) < 4){ pair<Ld, Ld>k = cir_inter_Ld(w[i], w[j]); (k.fr < k.se) && (c++), d.eb(k.fr, -1), d.eb(k.se, 1); } d.eb(PI * 2, 0), d.eb(PI, 0), sort(d.begin(), d.end()); Ld lst = 0;vt<pair<Ld, Ld>>s; FL(j, 0, sz(d) - 1){ if(!c)s.eb(lst, d[j].fr); c += d[j].se, lst = d[j].fr; } for(auto&a : s){ Ld l = cir_rotate_ang(w[i], a.fr).x, r = cir_rotate_ang(w[i], a.se).x; (l > r) && (swap(l, r), 1), imp.eb(l), imp.eb(r), arc.eb(w[i], !gt(a.se, PI), l, r); } } sort(imp.begin(), imp.end()), imp.erase(unique(imp.begin(), imp.end(), [](Ld&a, Ld&b){return fabsl(a - b) <= eps;}), imp.end()); int iz = imp.size();vt<vt<arcs>>bnd(iz - 1);Ld ans = 0; FL(i, 0, iz - 2){ long double l = imp[i], r = imp[i + 1];auto &a = bnd[i]; if(r - l <= eps)continue; for(auto&v : arc)if(v.l - eps <= l && r <= v.r + eps)a.eb(v.o, v.s, v.get(l), v.get(r)); sort(a.begin(), a.end(),[&](arcs&x, arcs&y)->bool {return x.l + x.r > y.l + y.r;}); for(int i = 0; i < sz(a); i += 2){ arcs&r1 = a[i], &r2 = a[i + 1]; Ld x1 = r1.get(l), x2 = r2.get(l), y1 = r1.get(r), y2 = r2.get(r); ans += (x1 - x2 + y1 - y2) * (r - l) / 2, r1.l = l, r1.r = r, r2.l = l, r2.r = r; ans += cir_seg_area(r1.o.r, r1.ang()) + cir_seg_area(r2.o.r, r2.ang()); } } return ans; } } int32_t main(){ int n;cin >> n;vt<cg::Cir>a(n); FL(i, 0, n - 1)cin >> a[i].o.x >> a[i].o.y >> a[i].r; printf("%.3Lf", cg::cir_inter_area(a)); return 0; }
|