计算几何

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

#define eps 1e-6

template<typename T> inline T abs_(T a) { return a < 0 ? -a : a; }
template<typename T> inline T min_(T a, T b) { return a < b ? a : b; }
template<typename T> inline T max_(T a, T b) { return a > b ? a : b; }

struct node {
	double x, y;
	inline node(double X, double Y) : x(X), y(Y) { }
	inline node() { x = y = 0; }
	inline bool operator > (const node &b) const { return abs_(y - b.y) < eps ? x > b.x : y > b.y; }
	inline bool operator < (const node &b) const { return abs_(y - b.y) < eps ? x < b.x : y < b.y; }
	inline bool operator == (const node &b) const { return abs_(x - b.x) < eps && abs_(y - b.y) < eps; }
	inline double mo() { return x * x + y * y; }
	inline double len() { return sqrt(mo()); }
};

inline bool equ(double a, double b) { return abs_(a - b) < eps; }
inline int dcmp(double x) { return abs_(x) < eps ? 0 : (x > 0 ? 1 : -1); }
inline double dist(node a, node b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
inline node vec(node a, node b) { return node(b.x - a.x, b.y - a.y); }
inline double operator * (node a, node b) { return a.x * b.x + a.y * b.y; }
inline node operator * (double k, node b) { return node(k * b.x, k * b.y); }
inline double operator ^ (node a, node b) { return a.x * b.y - a.y * b.x; }
inline node operator + (node a, node b) { return node(a.x + b.x, a.y + b.y); }
inline node operator - (node a, node b) { return node(a.x - b.x, a.y - b.y); }
inline int perp(node a, node b) { return dcmp(a * b); }
inline bool isinter(node a, node b, node p, node q) { return dcmp(((a - b) ^ (p - b)) * ((a - b) ^ (q - b))) < 0 && dcmp(((p - q) ^ (a - q)) * ((p - q) ^ (b - q))) < 0; }
inline node inter(node a, node b, node c, node d) { return a + (((a - c) ^ (d - c)) / ((d - c) ^ (b - a))) * (b - a); }
inline double dis(node a, node p, node q) { return p == q ? 0 : abs_((a - p) ^ (a - q)) / (p - q).len(); }
inline node foot(node c, node a, node b) { return a + (abs_(((c - a) * (c - b)) / (b - a).mo()) * (b - a)); }
inline node rotate(node a, double t) { return node(a.x * cos(t) - a.y * sin(t), a.y * cos(t) + a.x * sin(t)); }
inline double triarea(node a, node b, node c) { return abs_((a - b) ^ (a - c)) / 2.0; }
inline bool cmp(node a, node b) { return dcmp(a ^ b) > 0 || (equ(a ^ b, 0) && (a.mo() < b.mo())); }

#define poly vector<node>

inline double area(vector<node> A) {
	int n = A.size();
	if (n <= 2) return 0;
	double res = A[n - 1] ^ A[0];
	for (int i = 0; i < n - 1; ++i)
		res += A[i] ^ A[i + 1];
	return res / 2.0;
}

inline double length(vector<node> A) {
	int n = A.size(); double res = dist(A[0], A[n - 1]);
	for (int i = 0; i < n - 1; ++i)
		res += dist(A[i], A[i + 1]);
	return res;
}

namespace Conv {

int stk[N], top;

inline poly convex(poly a) {
	sort(a.begin(), a.end()); top = 0;
	poly res; int n = a.size(); node p = a[0];
	for (int i = 0; i < n; ++i) a[i] = a[i] - p;
	poly :: iterator tmp = a.begin();
	sort(++tmp, a.end(), cmp);
	stk[++top] = 0;
	for (int i = 1; i < n; ++i) {
		while (top > 1 && ((a[i] - a[stk[top - 1]]) ^ (a[stk[top]] - a[stk[top - 1]])) >= 0) --top;
		stk[++top] = i;
	}
	for (int i = 1; i <= top; ++i) res.push_back(a[stk[i]] + p);
	return res;
}

inline poly minkowski(poly a, poly b) {
	int n = a.size(), m = b.size();
	poly A, B;
	for (int i = 0; i < n; ++i) A.push_back(vec(a[i], a[(i + 1) % n]));
	for (int i = 0; i < m; ++i) B.push_back(vec(b[i], b[(i + 1) % m]));
	poly res; int i = 0, j = 0, cnt = 0; res.push_back(a[0] + b[0]);
	while (i < n && j < m) {
		res.push_back(res[cnt] + (dcmp(A[i] ^ B[j]) >= 0 ? A[i++] : B[j++]));
		++cnt;
	}
	while (i < n) {
		res.push_back(res[cnt] + A[i++]);
		++cnt;
	}
	while (j < m) {
		res.push_back(res[cnt] + B[j++]);
		++cnt;
	} return convex(res);
}

}

namespace Cartr {

poly cv;

inline double cartr(poly a) {
	cv = Conv :: convex(a); int n = cv.size();
	double ans = (cv[1] - cv[0]).mo(); int t = 0;
	for (int i = 0; i < n; ++i) {
		while (dis(cv[t], cv[i], cv[(i + 1) % n]) < dis(cv[(t + 1) % n], cv[i], cv[(i + 1) % n]))
			t = (t + 1) % n;
		ans = max_(ans, max_((cv[i] - cv[t]).mo(), (cv[(i + 1) % n] - cv[t]).mo()));
	} return ans;
}

}

node t;

inline bool checkin(poly &a, node x) {
	t = a[0];
	if (dcmp((x - t) ^ (a[0] - t)) > 0 || dcmp((*a.rbegin() - t) ^ (x - t)) > 0) return 0;
	poly :: iterator p = lower_bound(a.begin(), a.end(), x, [](node a, node b){return cmp(a - t, b - t);});
	--p; node i = *p, j; ++p;
	if (p == a.end()) j = a[0];
	else j = *p;
	return dcmp((x - i) ^ (j - i)) <= 0;
}

struct line {
	node a, b;
	inline line() { }
	inline line(double x1, double y1, double x2, double y2) : a(node(x1, y1)), b(node(x2, y2)) { }
	inline line(node A, node B) : a(A), b(B) { }
	inline bool operator < (const line &bb) {
		double t1 = atan2(b.y - a.y, b.x - a.x), t2 = atan2(bb.b.y - bb.a.y, bb.b.x - bb.a.x);
		if (abs_(t1 - t2) > eps) return t1 < t2;
		return ((bb.a - a) ^ (bb.b - a)) > eps;
	}
	inline bool operator > (const line &bb) {
		double t1 = atan2(b.y - a.y, b.x - a.x), t2 = atan2(bb.b.y - bb.a.y, bb.b.x - bb.a.x);
		if (abs_(t1 - t2) > eps) return t1 > t2;
		return ((bb.a - a) ^ (bb.b - a)) < -eps;
	}
	inline bool operator == (const line &bb) {
		return a == bb.a && b == bb.b;
	}
	inline double angle() {
		return atan2(b.y - a.y, b.x - a.x);
	}
};

inline node inter(line a, line b) {
	return inter(a.a, a.b, b.a, b.b);
}

namespace HP {
	
line q[N];
int l, r;
node p[N];
	
inline poly polyAnd(vector<line> &s) {
	int n = s.size(); sort(s.begin(), s.end());
	l = 1, r = 0;
	for (int i = 0; i < n; ++i) {
		if (i && equ(s[i].angle(), s[i - 1].angle())) continue;
		while (r > l && dcmp((s[i].b - p[r]) ^ (s[i].a - p[r])) > 0) --r;
		while (r > l && dcmp((s[i].b - p[l + 1]) ^ (s[i].a - p[l + 1])) > 0) ++l;
		q[++r] = s[i];
		if (r > l) p[r] = inter(q[r], q[r - 1]);
	}
	while (r > l && ((q[l].b - p[r]) ^ (q[l].a - p[r])) > eps) --r;
	p[r + 1] = inter(q[l], q[r]);
	++r; poly res;
	for (int i = l + 1; i <= r; ++i) res.push_back(p[i]);
	return res;
}
}

const double PI = acos(-1); 

struct circ {
	node o;
	double r;
	inline circ() { }
	inline circ(node O, double R) : o(O), r(R) { }
	inline circ(node a, node b, node c) {
		double A1 = 2 * (b.x - a.x), B1 = 2 * (b.y - a.y), C1 = b.mo() - a.mo();
		double A2 = 2 * (c.x - b.x), B2 = 2 * (c.y - b.y), C2 = c.mo() - b.mo();
		o = node((C1 * B2 - C2 * B1) / (A1 * B2 - A2 * B1), (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1));
		r = (a - o).len();
	}
	inline bool cover(const circ &p) { return (o - p.o).len() <= r - p.r; }
	inline bool cover(node p) { return dcmp(r - (p - o).len()) >= 0; }
	inline bool area() { return PI * r * r; }
};

inline circ minCover(poly a) {
	mt19937 rnd(time(0));
	shuffle(a.begin(), a.end(), rnd);
	circ res(node(0, 0), 0); int n = a.size();
	for (int i = 0; i < n; ++i) {
		if (!res.cover(a[i])) {
			res = circ(a[i], 0);
			for (int j = 0; j < i; ++j) {
				if (!res.cover(a[j])) {
					res = circ(0.5 * (a[i] + a[j]), (a[i] - a[j]).len() / 2);
					for (int k = 0; k < j; ++k) {
						if (!res.cover(a[k]))
							res = circ(a[i], a[j], a[k]);
					}
				}
			}
		}
	} return res;
}

李超树:

template<typename T> inline T abs_(T a) { return a < 0 ? -a : a; }
template<typename T> inline T min_(T a, T b) { return a < b ? a : b; }
template<typename T> inline T max_(T a, T b) { return a > b ? a : b; }

struct line {
	int x1, y1, x2, y2;
	
	inline double f(int x) {
		if (x1 == x2) return max_(y1, y2);
		return 1.0 * (y2 - y1) / (x2 - x1) * (x - x1) + y1;
	}
} p[100005];

int lc[N << 1 | 1], rc[N << 1 | 1], id[N << 1 | 1], ndnum = 0, rt = 0;

inline void insert(int &now, int l, int r, int x) {
	if (!now) now = ++ndnum;
	if (p[x].x1 <= l && r <= p[x].x2) {
		if (!id[now]) {
			id[now] = x;
			return ;
		}
		if (p[id[now]].f(l) >= p[x].f(l) && p[id[now]].f(r) >= p[x].f(r)) return ;
		if (p[id[now]].f(l) < p[x].f(l) && p[id[now]].f(r) < p[x].f(r)) { id[now] = x; return ; }
		int mid = l + r >> 1; if (p[id[now]].f(mid) < p[x].f(mid)) swap(id[now], x);
		if (p[id[now]].f(l) <= p[x].f(l)) insert(lc[now], l, mid, x);
		else insert(rc[now], mid + 1, r, x);
		return ;
	} int mid = l + r >> 1;
	if (p[x].x1 <= mid) insert(lc[now], l, mid, x);
	if (p[x].x2 > mid) insert(rc[now], mid + 1, r, x);
}

inline bool equ(double a, double b) {
	return abs_(a - b) < 1e-6;
}

inline int query(int now, int l, int r, int q) {
	if (!now) return 0;
	if (l >= r) return id[now];
	int res = 0, mid = l + r >> 1;
	if (q <= mid) res = query(lc[now], l, mid, q);
	if (q > mid) res = query(rc[now], mid + 1, r, q);
	if (!id[now]) return res;
	if (!res) return id[now];
	double a = p[id[now]].f(q), b = p[res].f(q);
	if (equ(a, b)) return min_(res, id[now]);
	return a < b ? res : id[now];
}

posted @ 2022-12-05 21:51  Smallbasic  阅读(31)  评论(0)    收藏  举报