Submission #984658

# Submission time Handle Problem Language Result Execution time Memory
984658 2024-05-17T00:50:41 Z crimson231 Lonely mdic (kriii1_L) C++17
0 / 1
2000 ms 452 KB
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <vector>
#include <deque>
typedef long long ll;
typedef double ld;
//typedef long double ld;
const ld INF = 1e17;
const ld TOL = 1e-10;
const ld PI = acos(-1);
const int LEN = 25;
int N, M, T, Q;
bool zero(const ld& x) { return std::abs(x) <= TOL; }
int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; }
ll sqr(ll x) { return x * x; }
ld norm(ld th) {
	while (th < 0) th += PI * 2;
	//while (th > PI * 2 - TOL) th -= PI * 2;
	while (th >= PI * 2) th -= PI * 2;
	return th;
}

//#define DEBUG
//#define ASSERT
struct Pii {
	int x, y;
	Pii(int X = 0, int Y = 0) : x(X), y(Y) {}
	bool operator == (const Pii& p) const { return x == p.x && y == p.y; }
	bool operator != (const Pii& p) const { return x != p.x || y != p.y; }
	bool operator < (const Pii& p) const { return x == p.x ? y < p.y : x < p.x; }
	bool operator <= (const Pii& p) const { return x == p.x ? y <= p.y : x <= p.x; }
	Pii operator + (const Pii& p) const { return { x + p.x, y + p.y }; }
	Pii operator - (const Pii& p) const { return { x - p.x, y - p.y }; }
	Pii operator * (const int& n) const { return { x * n, y * n }; }
	Pii operator / (const int& n) const { return { x / n, y / n }; }
	ll operator * (const Pii& p) const { return { (ll)x * p.x + (ll)y * p.y }; }
	ll operator / (const Pii& p) const { return { (ll)x * p.y - (ll)y * p.x }; }
	Pii& operator += (const Pii& p) { x += p.x; y += p.y; return *this; }
	Pii& operator -= (const Pii& p) { x -= p.x; y -= p.y; return *this; }
	Pii& operator *= (const int& scale) { x *= scale; y *= scale; return *this; }
	Pii& operator /= (const int& scale) { x /= scale; y /= scale; return *this; }
	Pii operator ~ () const { return { -y, x }; }
	Pii operator ! () const { return { -x, -y }; }
	ll xy() const { return (ll)x * y; }
	ll Euc() const { return (ll)x * x + (ll)y * y; }
	ld rad() const { return atan2(y, x); }
	int Man() const { return std::abs(x) + std::abs(y); }
	ld mag() const { return hypot(x, y); }
	friend std::istream& operator >> (std::istream& is, Pii& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pii& p) { os << p.x << " " << p.y; return os; }
};
const Pii Oii = { 0, 0 };
const Pii INF_PT = { (int)INF, (int)INF };
inline ll cross(const Pii& d1, const Pii& d2, const Pii& d3) { return (d2 - d1) / (d3 - d2); }
inline ll cross(const Pii& d1, const Pii& d2, const Pii& d3, const Pii& d4) { return (d2 - d1) / (d4 - d3); }
inline ll dot(const Pii& d1, const Pii& d2, const Pii& d3) { return (d2 - d1) * (d3 - d2); }
inline ll dot(const Pii& d1, const Pii& d2, const Pii& d3, const Pii& d4) { return (d2 - d1) * (d4 - d3); }
inline int ccw(const Pii& d1, const Pii& d2, const Pii& d3) {
	ll ret = cross(d1, d2, d3);
	return !ret ? 0 : ret > 0 ? 1 : -1;
}
struct Pos {
	ld x, y;
	Pos(ld X = 0, ld Y = 0) : x(X), y(Y) {}
	bool operator == (const Pos& p) const { return zero(x - p.x) && zero(y - p.y); }
	bool operator != (const Pos& p) const { return !zero(x - p.x) || !zero(y - p.y); }
	bool operator < (const Pos& p) const { return zero(x - p.x) ? y < p.y : x < p.x; }
	Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; }
	Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; }
	Pos operator * (const ld& scalar) const { return { x * scalar, y * scalar }; }
	Pos operator / (const ld& scalar) const { return { x / scalar, y / scalar }; }
	ld operator * (const Pos& p) const { return x * p.x + y * p.y; }
	ld operator / (const Pos& p) const { return x * p.y - y * p.x; }
	Pos operator ^ (const Pos& p) const { return { x * p.x, y * p.y }; }
	Pos operator - () const { return { -x, -y }; }
	Pos operator ~ () const { return { -y, x }; }
	Pos operator ! () const { return { y, x }; }
	Pos& operator += (const Pos& p) { x += p.x; y += p.y; return *this; }
	Pos& operator -= (const Pos& p) { x -= p.x; y -= p.y; return *this; }
	Pos& operator *= (const ld& scale) { x *= scale; y *= scale; return *this; }
	Pos& operator /= (const ld& scale) { x /= scale; y /= scale; return *this; }
	ld xy() const { return x * y; }
	Pos rot(ld the) const { return Pos(x * cos(the) - y * sin(the), x * sin(the) + y * cos(the)); }
	ld Euc() const { return x * x + y * y; }
	ld mag() const { return sqrt(Euc()); }
	//ld mag() const { return hypotl(x, y); }
	Pos unit() const { return *this / mag(); }
	ld rad() const { return norm(atan2(y, x)); }
	friend ld rad(const Pos& p1, const Pos& p2) { return norm(atan2(p1 / p2, p1 * p2)); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	friend bool cmpq(const Pos& a, const Pos& b) { return (a.quad() != b.quad()) ? a.quad() < b.quad() : a / b > 0; }
	bool close(const Pos& p) const { return zero((*this - p).Euc()); }
	friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; }
	friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; }
};
const Pos O = Pos(0, 0);
typedef std::vector<Pos> Polygon;
inline ld cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); }
inline int ccw(const Pos& d1, const Pos& d2, const Pos& d3) {
	ld ret = cross(d1, d2, d3);
	return zero(ret) ? 0 : ret > 0 ? 1 : -1;
}
Pos intersection(const Pos& p1, const Pos& p2, const Pos& q1, const Pos& q2) {
	ld a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}
struct Circle {
	Pii c;
	int r;
	Circle(Pii C = Pii(0, 0), int R = 0) : c(C), r(R) {}
	bool operator == (const Circle& C) const { return c == C.c && r == C.r; }
	bool operator != (const Circle& C) const { return !(*this == C); }
	bool operator < (const Circle& q) const {
		ll dist = sqr((ll)r - q.r);
		return r < q.r && dist >= (c - q.c).Euc();
	}
	bool operator > (const Pii& p) const { return r > (c - p).mag(); }
	bool operator >= (const Pii& p) const { return r + TOL > (c - p).mag(); }
	bool operator < (const Pii& p) const { return r < (c - p).mag(); }
	Circle operator + (const Circle& C) const { return { c + C.c, r + C.r }; }
	Circle operator - (const Circle& C) const { return { c - C.c, r - C.r }; }
	ld H(const ld& th) const { return sin(th) * c.x + cos(th) * c.y + r; }//coord trans | check right
	ld A() const { return 1. * r * r * PI; }
	friend std::istream& operator >> (std::istream& is, Circle& c) { is >> c.c >> c.r; return is; }
	friend std::ostream& operator << (std::ostream& os, const Circle& c) { os << c.c << " " << c.r; return os; }
};
bool cmpr(const Circle& p, const Circle& q) { return p.r > q.r; }//sort descending order
typedef std::vector<Circle> Disks;
struct Arc {
	ld lo, hi;// [lo, hi] - radian range of arc, 0 ~ 2pi
	Circle cen;
	Arc(ld LO = 0, ld HI = 0, Circle CEN = Circle(Pii(0, 0), 0)) : lo(LO), hi(HI), cen(CEN) {}
	bool operator < (const Arc& a) const { return zero(lo - a.lo) ? hi < a.hi : lo < a.lo; }
	ld area() const { return (hi - lo) * cen.r * cen.r; }
	ld green() const {
		Pos LO = -Pos(1, 0).rot(lo) * cen.r / 1;
		Pos HI = Pos(1, 0).rot(hi) * cen.r / 1;
		Pos vec = Pos(cen.c.x, cen.c.y);
		return (area() + vec / (HI + LO)) * .5;
		int x = cen.c.x, y = cen.c.y, r = cen.r;
		ld b = x * r * (sin(hi) - sin(lo));
		ld d = y * r * (cos(lo) - cos(hi));
		return (area() + b + d) * .5;
	}
	friend std::ostream& operator << (std::ostream& os, const Arc& l) { os << l.lo << " " << l.hi << " " << l.cen.r; return os; }
};
typedef std::vector<Arc> Arcs;
inline std::vector<Pos> intersection(const Circle& a, const Circle& b) {
	Pii ca = a.c, cb = b.c;
	Pii vec = cb - ca;
	ll ra = a.r, rb = b.r;
	ld distance = vec.mag();
	ld rd = vec.rad();

	if (vec.Euc() >= sqr(ra + rb)) return {};
	if (vec.Euc() <= sqr(ra - rb)) return {};

	//2nd hyprblc law of cos
	ld X = (ra * ra - rb * rb + vec.Euc()) / (2 * distance * ra);
	//if (X < -1 + TOL || X > 1 - TOL) return {};
	if (X < -1) X = -1;
	if (X > 1) X = 1;
	ld h = acos(X);
	if (zero(h)) return {};
	return { Pos(norm(rd - h), norm(rd + h)) };
}
inline ld union_except_x(const int& x, std::vector<Circle>& VC) {
	ld union_area = 0;
	int sz = VC.size();
	std::vector<bool> V(sz, 0);
	for (int i = 0; i < sz; i++) {
		if (i == x || V[i]) continue;
		Circle disk = VC[i];
		Arcs arcs;
		for (int j = 0; j < sz; j++) {
			if (j == x || j == i || V[j]) continue;
			Pii vec = VC[i].c - VC[j].c;
			ll ra = VC[i].r, rb = VC[j].r;
			if (vec.Euc() >= sqr(ra + rb)) continue;
			if (vec.Euc() <= sqr(ra - rb)) { V[j] = 1; continue; }
			auto inx = intersection(VC[i], VC[j]);
			//std::cout << inx.size() << "\n";
			if (!inx.size()) continue;
			ld lo = inx[0].x;
			ld hi = inx[0].y;

			Arc a1, a2;
			if (lo > hi) {
				a1 = Arc(lo, PI * 2, disk);
				a2 = Arc(0, hi, disk);
				arcs.push_back(a1);
				arcs.push_back(a2);
			}
			else {
				a1 = Arc(lo, hi, disk);
				arcs.push_back(a1);
			}
		}

		if (!arcs.size()) {
			//std::cout << "i : " << i << "\n";
			union_area += disk.A();
			continue;
		}

		std::sort(arcs.begin(), arcs.end());
		arcs.push_back(Arc(2 * PI, 2 * PI, disk));
		ld hi = 0;
		for (const Arc& a : arcs) {
			//std::cout << "arc[" << i << "] : " << a << "\n";
			if (a.lo > hi) union_area += Arc(hi, a.lo, disk).green(), hi = a.hi;
			else hi = std::max(hi, a.hi);
		}
	}
	return union_area;
}
void solve() {
	std::cin.tie(0)->sync_with_stdio(0);
	std::cout.tie(0);
	//std::cout << std::fixed;
	//std::cout.precision(3);

	int ret = 0;
	std::cin >> N;
	std::vector<Circle> tmp(N);
	std::vector<bool> V(N, 0);
	for (Circle& c : tmp) std::cin >> c;
	std::sort(tmp.begin(), tmp.end(), cmpr);
	//for (int i = 0; i < N; i++) {//remove
	//	if (V[i]) continue;
	//	for (int j = 0; j < N; j++) {
	//		//if (i < j && tmp[i] == tmp[j]) V[i] = 1;
	//		if (tmp[i] < tmp[j]) V[i] = 1;
	//		if (tmp[j] < tmp[i]) V[j] = 1;
	//	}
	//}

	Disks VC;
	for (int i = 0; i < N; i++) {
		if (!V[i]) VC.push_back(tmp[i]);
		if (V[i]) ret++;
	}

	int sz = VC.size();
	ld U = union_except_x(-1, VC);
	for (int x = 0; x < sz; x++) {
		ld A = union_except_x(x, VC);
		ret += zero(U - A);//no-dabwon
	}
	std::cout << ret << "\n";
}
int main() { solve(); return 0; }//boj10900 lonely mdic

/*

3
3 0 4
-3 0 4
0 0 2

5
0 0 1
1 1 1
-1 1 1
-1 -1 1
1 -1 1

9
3 0 4
-3 0 4
0 0 2
9 0 4
6 0 2
15 0 4
12 0 2
21 0 4
18 0 2

5
1000 1000 1415
1000 -1000 1415
-1000 -1000 1415
-1000 1000 1415
0 0 1

5
1000 1000 1414
1000 -1000 1414
-1000 -1000 1414
-1000 1000 1414
0 0 1



*/
# Verdict Execution time Memory Grader output
1 Correct 10 ms 452 KB Output is correct
2 Correct 7 ms 348 KB Output is correct
3 Correct 75 ms 348 KB Output is correct
4 Correct 66 ms 344 KB Output is correct
5 Correct 98 ms 344 KB Output is correct
6 Correct 106 ms 448 KB Output is correct
7 Execution timed out 2056 ms 348 KB Time limit exceeded
8 Halted 0 ms 0 KB -