← 全部文章

CF611G New Year and Cake 题解

本文目录(3 节)
  1. 题意
  2. 题解
  3. 代码

CF611G New Year and Cake

题意

  • 给定一个 nn 个顶点的严格凸多边形。
  • 要求 n(n−3)2\frac{n(n-3)}2 个由对角线将多边形割成两个部分的面积差 ×2\times 2 之和。
  • n≤5×105n \le 5 \times 10^5,答案对 109+710^9+7 取模。

题解

双指针扫一遍,动态维护对角线隔开的最大面积以及面积对答案的贡献和,其中贡献需要利用叉积的分配率维护有贡献的向量和。

注意本题根据写法不同可能需要开 unsigned long long,但同时需要对答案取模,因此细节很多。

代码

struct Po {
	int x, y;
	inline Po &operator -= (Po o) { return x -= o.x, y -= o.y, *this; }
	inline friend Po operator - (Po a, Po b) { return a -= b; }
	inline friend ll operator % (Po a, Po b) { return 1ll * a.x * b.y - 1ll * a.y * b.x; }
};

inline pair< modint, modint > &operator += (pair< modint, modint > &a, Po b) {
	return a.fi += (b.x % P + P) % P, a.se += (b.y % P + P) % P, a;
}

inline modint operator % (pair< modint, modint > a, Po b) {
	return a.fi * ((b.y % P + P) % P) - a.se * ((b.x % P + P) % P);
}

inline pair< modint, modint > operator * (modint a, Po b) {
	return mp(a * ((b.x % P + P) % P), a * ((b.y % P + P) % P));
}

inline pair< modint, modint > &operator -= (pair< modint, modint > &a, pair< modint, modint > b) {
	return a.fi -= b.fi, a.se -= b.se, a;
}

const int N = 5e5 + 7;
int n, cnt;
Po a[N];
modint ans, o;
pair< modint, modint > p;
ul s, m;

int main() {
	rd(n);
	for (int i = 0; i < n; i++) rd(a[i].x), rd(a[i].y);
	for (int i = 2; i < n; i++) s += (a[i] - a[0]) % (a[i-1] - a[0]);
	for (int i = 0, j = 0; i < n; i++) {
		while (1) {
			int k = (j + 1) % n;
			ul w = (a[k] - a[i]) % (a[j] - a[i]);
			if (2 * (m + w) >= s) {
				if (2 * (m + w) == s) ++cnt;
				break;
			}
			o += (m += w) % P;
			p += a[k] - a[i];
			j = k;
		}
		ans -= o * 2;
		int k = (i + 1) % n;
		m -= (a[j] - a[i]) % (a[k] - a[i]);
		o -= p % (a[k] - a[i]);
		p -= (modint)((j - i + n) % n) * (a[k] - a[i]);
	}
	ans += (modint)((1ll * n * (n - 3) - cnt) / 2 % P) * (modint)(s % P);
	print(ans);
	return 0;
}

标签:Two Pointers、计算几何

评论

    填写昵称即可留言。评论经站主审核后公开,请勿提交私人信息。

    正在连接评论服务…