【BZOJ】2289: 【POJ Challenge】圓,圓,圓
阿新 • • 發佈:2018-12-10
題解
二分一個橫座標,過這個橫座標做一條和y軸平行的直線,相當於在這條直線上做區間覆蓋,如果區間有交的話,那麼答案是True
否則的話取兩個不相交的區間,如果這兩個圓相離或相切則不合法
否則看看相交的部分在二分的橫座標的左邊還是右邊,進行更新
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,tot; bool dcmp(db a,db b) { return fabs(a - b) < eps; } struct Point { db x,y; Point(db _x = 0.0,db _y = 0.0) { x = _x;y = _y; } friend Point operator + (const Point &a,const Point &b) { return Point(a.x + b.x,a.y + b.y); } friend Point operator - (const Point &a,const Point &b) { return Point(a.x - b.x,a.y - b.y); } friend db operator * (const Point &a,const Point &b) { return a.x * b.y - a.y * b.x; } friend Point operator * (const Point &a,const db &d) { return Point(a.x * d,a.y * d); } friend Point operator / (const Point &a,const db &d) { return Point(a.x / d,a.y / d); } friend db dot(const Point &a,const Point &b) { return a.x * b.x + a.y * b.y; } db norm() { return x * x + y * y; } }; struct Circle { Point O; db R; }C[MAXN]; struct line { db s,t; int id; friend bool operator < (const line &a,const line &b) { return a.t < b.t || (a.t == b.t && a.s < b.s); } }L[MAXN]; db dis(Point a,Point b) { return sqrt((b - a).norm()); } int check(db mid) { tot = 0; for(int i = 1 ; i <= N ; ++i) { if(fabs(mid - C[i].O.x) >= C[i].R) { if(mid > C[i].O.x) return -1; else return 1; } db t = sqrt(C[i].R * C[i].R - (C[i].O.x - mid) * (C[i].O.x - mid)); L[++tot] = (line){C[i].O.y - t,C[i].O.y + t,i}; } sort(L + 1,L + tot + 1); db a = L[1].s,b = L[1].t; for(int i = 2 ; i <= N ; ++i) { a = max(a,L[i].s);b = min(b,L[i].t); } if(a + eps < b) return 0; for(int i = 2 ; i <= N ; ++i) { if(L[i].s >= L[1].t) { int u = L[1].id,v = L[i].id; if(dis(C[u].O,C[v].O) >= C[u].R + C[v].R) return -2; else { Point p = C[u].O + (C[v].O - C[u].O) * (C[u].R / dis(C[v].O,C[u].O)); if(p.x < mid) return -1; else return 1; } } } } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { scanf("%lf%lf%lf",&C[i].O.x,&C[i].O.y,&C[i].R); } db L = C[1].O.x - C[1].R,R = C[1].O.x + C[1].R; for(int i = 2 ; i <= N ; ++i) { L = min(L,C[i].O.x - C[i].R); R = max(R,C[i].O.x + C[i].R); } int cnt = 50; while(cnt--) { db mid = (L + R) / 2; int x = check(mid); if(x == -2) {puts("NO");return;} if(x == 0) {puts("YES");return;} if(x == -1) {R = mid;} else {L = mid;} } if(check(L) != 0) puts("NO"); else puts("YES"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }