CF951E

题意

给平面上 \(n\) 个无三点共线和重点的点。
问有多少种方法选出两个三角形不相交。

\(3\ \leq\ n\ \leq\ 2000,\ -10^9\ \leq\ x,\ y\ \leq\ 10^9\)

做法1

对于两不相交的三角形 \(\{a_0,\ a_1,\ a_2\},\ \{b_0,\ b_1,\ b_2\}\),过 \(a_x,\ b_y\ (0\ \leq\ x,\ y\ \leq\ 2)\) 做直线,得到的所有直线中恰有两条将两个三角形分在两边。
所以直接对平面上每两个点连出的直线统计左右两侧分别多少个点即可。
时间复杂度 \(O(n^2\ log\ n)\)

代码

#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif

using namespace std;

const int maxn = 2010;

struct point {
	int x, y;

	point() {}
	point(int x, int y): x(x), y(y) {}
} a[maxn];

point operator - (const point &a, const point &b) { return point(a.x - b.x, a.y - b.y); }
long long det(const point &a, const point &b) { return (long long) a.x * b.y - (long long) a.y * b.x; }
bool operator < (const point &a, const point &b) { return det(a, b) > 0; }

long long C2(int n) { return (long long) n * (n - 1) >> 1; }

int n, m, c[maxn];
pair<point, pair<int, int> > b[maxn * maxn];
long long ans;

int main() {
	scanf("%d", &n);
	for (int x, y, i = 1; i <= n; ++i) scanf("%d%d", &x, &y), a[i] = point(x, y);
	sort(a + 1, a + n + 1, [&](point s, point t) { return s.x < t.x || s.x == t.x && s.y < t.y; });
	for (int i = 1; i <= n; ++i) for (int j = 1; j < i; ++j) b[m++] = make_pair(a[i] - a[j], make_pair(i, j));
	sort(b, b + m);
	for (int i = 1; i <= n; ++i) c[i] = i;
	for (int i = 0; i < m; ++i) {
		int x = c[b[i].second.first], y = c[b[i].second.second];
		if(x > y) swap(x, y);
		ans += C2(x - 1) * C2(n - y);
		swap(c[b[i].second.first], c[b[i].second.second]);
	}
	printf("%"LLFORMAT"d\n", ans);
	return 0;
}


posted @ 2018-08-22 15:15  King_George  阅读(324)  评论(0编辑  收藏  举报