【题解】NOIp模拟:四轮车

在地图上散落着 n 个车轮,小 J 想用它们造一辆车。要求如下:

  1. 一辆车需要四个车轮,且四个车轮构成一个正方形

  2. 车轮不能移动你需要计算有多少种造车的方案(两个方案不同当且仅当所用车轮不全相同,坐标相同的两个车轮视为不同车轮)。

30%的数据保证 n ≤ 30
100%的数据保证 1 ≤ n ≤ 1000; |x|, |y| < 20000

O ( n 2 ) O(n^2) 枚举两个点,计算出另外两个点,用二分求出另外两个点的方案数,用乘法原理乘起来,最终要除以2

Code:

#include <bits/stdc++.h>
#define maxn 1010
#define LL long long
using namespace std;
struct node{
	int x, y;
}a[maxn];
int n;
LL ans;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

bool cmp(node x, node y){ return x.x == y.x ? x.y < y.y : x.x < y.x; }

LL check(int x, int y){
	int l = 1, r = n, ansl = 0, ansr = 0;
	while (l <= r){
		int mid = (l + r) >> 1;
		if (a[mid].x < x) l = mid + 1;
		else if (a[mid].x > x) r = mid - 1;
		else if (a[mid].y > y) r = mid - 1;
		else if (a[mid].y < y) l = mid + 1;
		else ansl = mid, r = mid - 1;
	}
	l = 1, r = n;
	while (l <= r){
		int mid = (l + r) >> 1;
		if (a[mid].x < x) l = mid + 1;
		else if (a[mid].x > x) r = mid - 1;
		else if (a[mid].y > y) r = mid - 1;
		else if (a[mid].y < y) l = mid + 1;
		else ansr = mid, l = mid + 1;
	}
	if (!ansl || !ansr) return 0; else return ansr - ansl + 1;
}

int main(){
	freopen("car.in", "r", stdin);
	freopen("car.out", "w", stdout);
	n = read();
	for (int i = 1; i <= n; ++i) a[i].x = read(), a[i].y = read();
	sort(a + 1, a + 1 + n, cmp);
	for (int i = 1; i <= n; ++i)
		for (int j = i + 1; j <= n; ++j){
			node x = a[i], y = a[j];
			if (a[i].x == a[j].x && a[i].y == a[j].y) continue;
			node tx = (node){x.x + y.y - x.y, x.x + x.y - y.x};
			node ty = (node){tx.x + y.x - x.x, tx.y + y.y - x.y};
			LL ansx = check(tx.x, tx.y), ansy = check(ty.x, ty.y);
			if (ansx && ansy) ans += ansx * ansy;
			// printf("(%d,%d),(%d,%d),(%d,%d),(%d,%d)\n", x.x, x.y, y.x, y.y, tx.x, tx.y, ty.x, ty.y);
		}
	printf("%lld\n", ans >> 1);
}

猜你喜欢

转载自blog.csdn.net/ModestCoder_/article/details/108219394