【BZOJ 3053】The Closest M Points
KDTree模板,在m维空间中找最近的k个点,用的是欧几里德距离。
理解了好久,昨晚始终不明白那些“估价函数”,后来才知道分情况讨论,≤k还是=k,在当前这一维度距离过线还是不过线,过线则要继续搜索另一个子树。还有别忘了当前这个节点!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() using namespace std; typedef long long LL; const int N = 50003; const int inf = 0x7fffffff; int getint() { int k = 0, fh = 1; char c = getchar (); for (; c < '0' || c > '9' ; c = getchar ()) if (c == '-' ) fh = -1; for (; c >= '0' && c <= '9' ; c = getchar ()) k = k * 10 + c - '0' ; return k * fh; } int n, m, root, D; LL minn; struct P { int d[5], mx[5], mn[5], l, r, id; P (): l(0), r(0), id(0) {}; int &operator [] ( int x) { return d[x];} bool operator < (P point) const { return d[D] < point[D];} } T[N << 1], po[N]; priority_queue <pair <LL, int > > Q; LL sqr(LL x) { return x * x;} LL dis(P a, P b) { LL ret = 0; for ( int i = 0; i < m; ++i) ret += sqr(a[i] - b[i]); return ret; } void pushup( int x, int y) { for ( int i = 0; i < m; ++i) T[x].mn[i] = min(T[x].mn[i], T[y].mn[i]), T[x].mx[i] = max(T[x].mx[i], T[y].mx[i]); } int Build( int l, int r, int dd) { D = dd; int mid = (l + r) >> 1; nth_element(po + l, po + mid, po + r + 1); for ( int i = 0; i < m; ++i) T[mid].mn[i] = T[mid].mx[i] = T[mid].d[i] = po[mid].d[i]; T[mid].id = mid; if (l < mid) T[mid].l = Build(l, mid - 1, (dd + 1) % m); if (mid < r) T[mid].r = Build(mid + 1, r, (dd + 1) % m); if (T[mid].l) pushup(mid, T[mid].l); if (T[mid].r) pushup(mid, T[mid].r); return mid; } void ask( int rt, int dd, P p, int k) { int L = T[rt].l, R = T[rt].r; if (p[dd] >= T[rt][dd]) swap(L, R); if (L) ask(L, (dd + 1) % m, p, k); bool pd = 0; LL di = dis(T[rt], p); minn = min(minn, di); if (Q.size() < k) { Q.push(pair <LL, int > (di, rt)); pd = 1;} else { if (di < Q.top().first) Q.pop(), Q.push(make_pair(di, rt)); if (sqr(p[dd] - T[rt][dd]) < Q.top().first) pd = 1; } if (pd && R) ask(R, (dd + 1) % m, p, k); } int ans[N]; int main() { while (~ scanf ( "%d%d" , &n, &m)) { for ( int i = 1; i <= n; ++i) for ( int j = 0; j < m; ++j) read(po[i][j]); memset (T, 0, sizeof (T)); root = Build(1, n, 0); int qq; read(qq); for (; qq; --qq) { P p; int k; for ( int i = 0; i < m; ++i) read(p[i]); read(k); printf ( "the closest %d points are:\n" , k); minn = inf; ask(root, 0, p, k); while (!Q.empty()) { ans[++ans[0]] = Q.top().second; Q.pop(); } for (; ans[0]; --ans[0]) for ( int i = 0; i < m; ++i) printf ( "%d%c" , T[ans[ans[0]]][i], " \n" [i == m - 1]); } } return 0; } |
我就是弱啊~~~
NOI 2017 Bless All
分类:
数据结构-KDTree
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!