离线按cost排序,先把所有节点标记为不可用,然后边扫边标记就行了,复杂度O(mlog(n)) (最坏O(msqrt(n)))
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 1LL<<62;
const int maxn = 2e5 + 10;
const int D = 2;
bool vis[maxn];
int T, N, M, cmp_idx, split[maxn];
LL ans;
struct Node {
int id, cost;
LL val[D];
}node[maxn], temp[maxn], q, res, cus[maxn], output[maxn];
bool cmp1(const Node &a, const Node &b) {
return a.val[cmp_idx] < b.val[cmp_idx];
}
bool cmp2(const Node &a, const Node &b) {
return a.cost < b.cost;
}
void build(int l, int r, int idx) {
if (l > r) return;
int mid = (l + r)>>1;
split[mid] = cmp_idx = idx;
nth_element(node+l, node+mid, node+r+1, cmp1);
build(l, mid-1, idx^1); build(mid+1, r, idx^1);
}
void query(int l, int r) {
if (l > r) return;
int mid = (l + r)>>1;
if (!vis[node[mid].id]) {
LL dis = 0;
for (int i = 0; i < D; i++) dis += (q.val[i]-node[mid].val[i])*(q.val[i]-node[mid].val[i]);
if (dis < ans) {
ans = dis;
res = node[mid];
}
else if (dis == ans && node[mid].id < res.id) {
res = node[mid];
}
}
int s = split[mid];
LL radius = (q.val[s]-node[mid].val[s])*(q.val[s]-node[mid].val[s]);
if (q.val[s] < node[mid].val[s]) {
query(l, mid-1);
if (radius <= ans) query(mid+1, r);
}
else {
query(mid+1, r);
if (radius <= ans) query(l, mid-1);
}
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d %d", &N, &M);
for (int i = 1; i <= N; i++) {
node[i].id = i;
for (int j = 0; j < D; j++) scanf("%lld", &node[i].val[j]);
scanf("%d", &node[i].cost);
temp[i] = node[i];
}
for (int i = 1; i <= M; i++) {
cus[i].id = i;
for (int j = 0; j < D; j++) scanf("%lld", &cus[i].val[j]);
scanf("%d", &cus[i].cost);
}
build(1, N, 0);
for (int i = 1; i <= N; i++) vis[i] = 1;
int p = 1;
sort(temp+1, temp+1+N, cmp2);
sort(cus+1, cus+1+M, cmp2);
for (int i = 1; i <= M; i++) {
while (p <= N && temp[p].cost <= cus[i].cost) {
vis[temp[p].id] = 0;
p++;
}
ans = INF;
q = cus[i];
query(1, N);
output[cus[i].id] = res;
}
for (int i = 1; i <= M; i++) {
for (int j = 0; j < D; j++) printf("%lld ", output[i].val[j]);
printf("%d\n", output[i].cost);
}
}
return 0;
}