P2038 - [蓝桥杯2022初赛] 扫雷 - New Online Judgehttp://oj.ecustacm.cn/problem.php?id=2038
暴力能过30%
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 4;
struct node {
int x, y, r;
};
node a[N], b[N];
int vis[N] = {0};
int n, m, ans = 0;
int within(node p, node q) {
int dis2 = (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y);
return dis2 <= q.r * q.r;
}
void blowUp(node q) {
for (int i = 0; i < n; i++) {
if (!vis[i]) {
if (within(a[i], q)) {
vis[i] = 1;
ans++;
blowUp(a[i]);
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> a[i].x >> a[i].y >> a[i].r;
}
for (int i = 0; i < m; i++) {
cin >> b[i].x >> b[i].y >> b[i].r;
}
for (int j = 0; j < m; j++) {
blowUp(b[j]);
}
cout << ans;
return 0;
}
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 4;
struct node {
int x, y, r;
};
node a[N], b[N];
int vis[N] = {0};
int n, m, ans = 0;
int within(node& p, node& q) {
int dis2 = (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y);
return dis2 <= q.r * q.r;
}
int first(node& q) {
int low = 0, high = n - 1;
while (low < high) {
int mid = (low + high) >> 1;
if (a[mid].x < q.x - q.r) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
void blowUp(node& q) {
int i = first(q);
for (; i < n; i++) {
if (a[i].x > q.x + q.r) {
break;
}
if (!vis[i]) {
if (within(a[i], q)) {
vis[i] = 1;
ans++;
blowUp(a[i]);
}
}
}
}
int cmp(node& p, node& q) {
return p.x < q.x;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> a[i].x >> a[i].y >> a[i].r;
}
for (int i = 0; i < m; i++) {
cin >> b[i].x >> b[i].y >> b[i].r;
}
sort(a, a + n, cmp);
for (int j = 0; j < m; j++) {
blowUp(b[j]);
}
cout << ans;
return 0;
}
先对炸雷按x的值排序,每次爆炸的q能引爆的炸雷的x值肯定在区间[q.x-q.r,q.x+q.r]内,所以可以二分枚举出第一个x值>=q.x-q.r的炸雷,减少每次遍历的范围