【CodeChef】Imagine Polygons

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/84926958

【题目链接】

【思路要点】

  • 首先显然的一点是当且仅当两个多边形在 x x 轴上的跨度不一样,输出 1 -1
  • 考虑一个 x x 轴上的坐标 i i ,在满足 x = i x=i 的平面上的任意一点 ( i , y , z ) (i,y,z) 能够被计入答案当且仅当 ( i , y ) (i,y) x y x-y 轴的投影多边形内, ( i , z ) (i,z) x z x-z 轴的投影多边形内。
  • 令直线 x = i x=i x y x-y 轴的投影多边形的公共部分长度为 f ( i ) f(i) ,与 x z x-z 轴的投影多边形的公共部分长度为 g ( i ) g(i) ,则答案为 M i n x M a x x f ( x ) g ( x ) d x \int_{Minx}^{Maxx}f(x)*g(x)*dx
  • x x 轴按照出现过的 x x 坐标分段,每一段的 f ( x ) , g ( x ) f(x),g(x) 均为一次函数,可以方便地求解定积分。
  • 时间复杂度 O ( ( N + M ) L o g ( N + M ) ) O((N+M)Log(N+M))

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
struct point {double x, y; };
point operator + (point a, point b) {return (point) {a.x + b.x, a.y + b.y}; }
point operator - (point a, point b) {return (point) {a.x - b.x, a.y - b.y}; }
point a[MAXN], b[MAXN], sa[MAXN], sb[MAXN];
int n, m, tot; double p[MAXN];
set <double> st; map <double, int> home;
double Int(double l, double r, double a, double b, double c) {
	double ans = (r - l) * c;
	ans += (r * r / 2 - l * l / 2) * b;
	ans += (r * r * r / 3 - l * l * l / 3) * a;
	return ans;
}
int main() {
	int T; read(T);
	while (T--) {
		tot = 0;
		st.clear();
		home.clear();
		read(n);
		double Mina = 1e10, Maxa = -1e10;
		for (int i = 1; i <= n; i++) {
			read(a[i].x), read(a[i].y);
			st.insert(a[i].x);
			chkmin(Mina, a[i].x);
			chkmax(Maxa, a[i].x);
			sa[i] = (point) {0, 0};
		}
		a[n + 1] = a[1];
		read(m);
		double Minb = 1e10, Maxb = -1e10;
		for (int i = 1; i <= m; i++) {
			read(b[i].x), read(b[i].y);
			st.insert(b[i].x);
			chkmin(Minb, b[i].x);
			chkmax(Maxb, b[i].x);
			sb[i] = (point) {0, 0};
		}
		if (Minb != Mina || Maxb != Maxa) {
			puts("-1");
			continue;
		}
		b[m + 1] = b[1];
		for (auto x : st) {
			p[++tot] = x;
			home[x] = tot;
		}
		for (int i = 1; i <= n; i++) {
			int l = home[a[i].x], r = home[a[i + 1].x];
			double k = (a[i + 1].y - a[i].y) / (a[i + 1].x - a[i].x);
			if (l < r) sa[l] = sa[l] - (point) {k, a[i].y - k * a[i].x}, sa[r] = sa[r] + (point) {k, a[i].y - k * a[i].x};
			else if (l > r) sa[l] = sa[l] - (point) {k, a[i + 1].y - k * a[i + 1].x}, sa[r] = sa[r] + (point) {k, a[i + 1].y - k * a[i + 1].x};
		}
		for (int i = 1; i <= m; i++) {
			int l = home[b[i].x], r = home[b[i + 1].x];
			double k = (b[i + 1].y - b[i].y) / (b[i + 1].x - b[i].x);
			if (l < r) sb[l] = sb[l] - (point) {k, b[i].y - k * b[i].x}, sb[r] = sb[r] + (point) {k, b[i].y - k * b[i].x};
			else if (l > r) sb[l] = sb[l] - (point) {k, b[i + 1].y - k * b[i + 1].x}, sb[r] = sb[r] + (point) {k, b[i + 1].y - k * b[i + 1].x};
		}
		double ans = 0;
		for (int i = 1; i <= tot - 1; i++) {
			sa[i] = sa[i - 1] + sa[i];
			sb[i] = sb[i - 1] + sb[i];
			ans += Int(p[i], p[i + 1], sa[i].x * sb[i].x, sa[i].x * sb[i].y + sa[i].y * sb[i].x, sa[i].y * sb[i].y);
		}
		printf("%.10lf\n", ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/84926958
今日推荐