当前位置: 首页 > news >正文

数据结构 Trick 之:KDT 求 k 近/远 点

注意,此 Trick 的时间复杂度是错的,但是貌似目前没人能卡满。

能够解决的问题

  • \(O(n \sqrt n)\) 可过。
  • 维护二维平面。
  • 每次求到一个点的 \(k\) 近或 \(k\) 远点。
  • \(k\) 很小(\(20\) 左右)

思路

二维空间想到 KDTree(TreeKevin Durant Tree)。

众所周知,动态维护 \(k\) 近或 \(k\) 远点只需要一个 \(k\) 个点的堆即可,那么我们就有了一个剪枝:当前节点维护的区间到询问点的理论极值(写个估价函数就行)都比不上当前 \(k\) 大/小值,就返回。

结束了,就是这么简单。

例题与代码

P2093 [国家集训队] JZPFAR - 洛谷

#include <bits/stdc++.h>
using namespace std;namespace gxk {void main() ;
}
int main() {ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);gxk::main();return 0;
}// ---#define int long long
namespace gxk {constexpr int maxn = 100010;struct point {int x[2];} p;int n, m, x, b[maxn];struct value {int dis, idx;bool operator < (const value o) const {return dis > o.dis || (dis == o.dis && idx < o.idx);}} ;priority_queue <value> q;struct Kevin_DurantNode {point x, l, r;int ls, rs, idx;} nodes[maxn];int cnt;struct Kevin_DurantTree {void pushup(int u) {for (int k = 0; k < 2; k++) {nodes[u].l.x[k] = nodes[u].r.x[k] = nodes[u].x.x[k];if (nodes[u].ls) {nodes[u].l.x[k] = min(nodes[u].l.x[k], nodes[nodes[u].ls].l.x[k]);nodes[u].r.x[k] = max(nodes[u].r.x[k], nodes[nodes[u].ls].r.x[k]);}if (nodes[u].rs) {nodes[u].l.x[k] = min(nodes[u].l.x[k], nodes[nodes[u].rs].l.x[k]);nodes[u].r.x[k] = max(nodes[u].r.x[k], nodes[nodes[u].rs].r.x[k]);}}return ;}void build(int &u, int l, int r, int k) {int midd = ((l + r) >> 1);nth_element(b + l, b + midd, b + r + 1, [k](int a, int b){return nodes[a].x.x[k] < nodes[b].x.x[k];});u = b[midd];
//			cout << nodes[u].x.x[0] << ' ' << nodes[u].x.x[1] << '\n';if (l < midd) build(nodes[u].ls, l, midd - 1, k ^ 1);if (r > midd) build(nodes[u].rs, midd + 1, r, k ^ 1);pushup(u);return ;}int dis(int x, int y) {return (x - p.x[0]) * (x - p.x[0]) + (y - p.x[1]) * (y - p.x[1]);}int evaluate(int u) {return max({dis(nodes[u].l.x[0], nodes[u].l.x[1]), dis(nodes[u].l.x[0], nodes[u].r.x[1]), dis(nodes[u].r.x[0], nodes[u].l.x[1]), dis(nodes[u].r.x[0], nodes[u].r.x[1])});}void query(int u) {value now = {evaluate(u), nodes[u].idx};if (!(now < q.top())) return ;now = {dis(nodes[u].x.x[0], nodes[u].x.x[1]), nodes[u].idx};if (now < q.top()) q.pop(), q.push(now);if (nodes[u].ls && nodes[u].rs) {value vl = {evaluate(nodes[u].ls), nodes[nodes[u].ls].idx}, vr = {evaluate(nodes[u].rs), nodes[nodes[u].rs].idx};if (vl < vr) {query(nodes[u].ls);query(nodes[u].rs);} else {query(nodes[u].rs);query(nodes[u].ls);}} else if (nodes[u].ls) {query(nodes[u].ls);} else if (nodes[u].rs) {query(nodes[u].rs);}return ;}} kdt;int root;void main() {cin >> n;cnt = n;for (int i = 1; i <= n; i++) {cin >> nodes[i].x.x[0] >> nodes[i].x.x[1];nodes[i].idx = i;b[i] = i;}kdt.build(root, 1, n, 0);cin >> m;while (m--) {cin >> p.x[0] >> p.x[1] >> x;while (!q.empty()) q.pop();while (x--) {q.push({-1, 0});}kdt.query(root);cout << q.top().idx << '\n';}return ;}
}
http://www.wxhsa.cn/company.asp?id=7964

相关文章:

  • .NET 8程序配置版本及产品信息
  • C语言第二讲:进制转化
  • XXL-JOB(4)
  • QOJ #10485. Peculiar Protocol 题解
  • C++ 常用关键字
  • 【AP出版】第四届数理统计与经济分析国际学术会议 (MSEA 2025)
  • 数据结构 Trick 之:区间子区间计数
  • mapstruct.Mapper|Mapping详解
  • 抽象代数-学习笔记
  • 如何在保证质量的前提下,快速完成一份 PPT?
  • Source Code Summarization in the Era of Large Language Models 论文笔记
  • 线性回归-入门案例
  • XXL-JOB(3)
  • ClickHouse 表引擎深度解析:ReplacingMergeTree、PARTITION、PRIMARY KEY、ORDER BY 详解 - 若
  • UOS统信服务器操作系统V20(1070)安装mysql8.4.5(建议安装glibc2.28版本)
  • web5(phps源码泄露)
  • web3(自带网络工具包查看数据)
  • web17(备份的sql文件泄露)
  • web11(通过Dns检查查询Flag)
  • ctfshow_web11
  • ctfshow_web13
  • ctfshow_web9
  • 锁屏界面无法通过任意键弹出开机密码
  • 应急响应-日志分析 - voasem
  • ctfshow web 10
  • SMA的射频连接器
  • 什么是Elasticsearch?它与其他搜索引擎相比有什么优势?
  • pdf.js-2.3.0国内下载地址
  • opencv学习记录2
  • get请求图片文件转为base64编码