2019牛客多校训练第十场F Popping Balloons

2019牛客多校训练第十场F Popping Balloons

题意:二维平面内给你若干个点,然后你可以在x轴和y轴分别射三枪(每一枪的间隔是R),问最多能射掉多少气球。

题解:贪心。这个应该只能算作假算法吧。。。。不过大佬的思想还是很厉害。
A:用一个哈希数组来记录x轴每一列有多少对应的气球,然后排序。假设当前的x坐标就是第一枪的坐标,然后记录有多少个气球能这样能击破。
B:然后从大到小排序,只遍历前1000个。(这就是有问题的地方,但是过了,可能是数据水吧。咖啡鸡后来说:其实这个应该可以过,因为整个答案的确会一定落在√n以内的地方。证明的话不是很清楚,不过我目前没有反例。)
C:然后每一个x坐标遍历,寻找y,并哈希记录,去找到最大的气球总值。输出。

闲话:比赛中隔壁队伍建立1e5颗线段树后树套树过了,导致比赛的时候绞尽脑汁想树套树到结束,结束一看大佬代码给跪了。看看明天能不能把题解的算法补一下。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mx = 5e5 + 7;
struct node {
	int x, y,xnum;
}a[mx],ha[mx];
inline bool cmp(node a, node b) {
	return a.xnum > b.xnum;
}
int hx[mx * 2] = { 0 }, hy[mx * 2] = { 0 };
int ans = 0;
int main() {
	int n, r;
	scanf("%d%d", &n, &r);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &a[i].x, &a[i].y);
		hx[a[i].x]++;
	}
	for (int i = 0; i < mx; i++) {
		ha[i].xnum = hx[i] + hx[i + r] + hx[i + 2 * r];
		ha[i].x = i;
	}
	sort(ha, ha + mx, cmp);
	for (int i = 0; i <= 1000; i++) {
		memset(hy, 0, sizeof(hy));
		for (int j = 1; j <= n; j++) {
			if (ha[i].x != a[j].x && (ha[i].x + r) != a[j].x && (ha[i].x + 2 * r) != a[j].x)
				hy[a[j].y]++;
		}
		int manx = -1;
		for (int j = 0; j <= mx; j++) {
			manx = max(manx, hy[j] + hy[j + r] + hy[j + 2 * r]);
		}
		ans = max(ans, ha[i].xnum + manx);
	}
	printf("%d\n", ans);
	return 0;
}

你可能感兴趣的:(贪心,思维)