SJY摆棋子 题解
作者:互联网
一、题目:
二、思路:
本题是KD树的模板题。废话不多说直接上模板。
三、实现细节
注意nth_element的使用。还有就是什么时候暴力重构整棵树。
这些思想都非常有趣,也非常暴力。
这种数据结构网上没有什么好的模板(实际上是我懒得去找了),只能自己打,调了很长时间。发篇博客纪念一下。
四、代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
#define mem(s, v) memset(s, v, sizeof s)
#define FILEIN(s) freopen(s".in", "r", stdin)
#define FILEOUT(s) freopen(s".out", "w", stdout)
inline LL read(void) {
LL x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return f * x;
}
const int maxn = 1e6 + 5, base = 25000;
const LL inf = 1e12;
int n, sz, m;
LL ans;
bool dimension;
struct Node {
LL x, y;
int ls, rs;
bool d;
LL xmin, xmax, ymin, ymax;
}a[maxn], tr[maxn];
inline bool cmp(const Node& x, const Node& y) {
if (dimension) return x.x < y.x;
return x.y < y.y;
}
inline int new_node(LL x, LL y, bool d) {
tr[++sz].x = x; tr[sz].y = y;
tr[sz].d = d;
tr[sz].xmin = tr[sz].xmax = x;
tr[sz].ymin = tr[sz].ymax = y;
return sz;
}
inline void pushup(int o) {
int ls = tr[o].ls, rs = tr[o].rs;
tr[o].xmin = min(tr[o].xmin, min(tr[ls].xmin, tr[rs].xmin));
tr[o].xmax = max(tr[o].xmax, max(tr[ls].xmax, tr[rs].xmax));
tr[o].ymin = min(tr[o].ymin, min(tr[ls].ymin, tr[rs].ymin));
tr[o].ymax = max(tr[o].ymax, max(tr[ls].ymax, tr[rs].ymax));
}
int build(int l, int r, bool d) {
if (l > r) return 0;
int mid = (l + r) >> 1;
dimension = d;
nth_element(a + l, a + mid, a + r + 1, cmp);
int tmp = new_node(a[mid].x, a[mid].y, d);
tr[tmp].ls = build(l, mid - 1, d ^ 1);
tr[tmp].rs = build(mid + 1, r, d ^ 1);
pushup(tmp);
return tmp;
}
int insert(int o, LL x, LL y, bool d) {
if (!o) return new_node(x, y, d);
if (d == 1) {
if (x < tr[o].x) tr[o].ls = insert(tr[o].ls, x, y, d ^ 1);
else tr[o].rs = insert(tr[o].rs, x, y, d ^ 1);
}
else {
if (y < tr[o].y) tr[o].ls = insert(tr[o].ls, x, y, d ^ 1);
else tr[o].rs = insert(tr[o].rs, x, y, d ^ 1);
}
pushup(o);
return o;
}
inline LL calc(LL x1, LL y1, LL x2, LL y2) {
return abs(x1 - x2) + abs(y1 - y2);
}
inline LL get_lower_bound(int o, LL x, LL y) {
LL res = 0;
if (tr[o].xmax < x) res += x - tr[o].xmax;
if (tr[o].ymax < y) res += y - tr[o].ymax;
if (tr[o].xmin > x) res += tr[o].xmin - x;
if (tr[o].ymin > y) res += tr[o].ymin - y;
return res;
}
void query(int o, LL x, LL y) {
if (!o) return;
ans = min(ans, calc(tr[o].x, tr[o].y, x, y));
LL d1 = get_lower_bound(tr[o].ls, x, y), d2 = get_lower_bound(tr[o].rs, x, y);
if (d1 < d2) {
if (d1 < ans) query(tr[o].ls, x, y);
if (d2 < ans) query(tr[o].rs, x, y);
}
else {
if (d2 < ans) query(tr[o].rs, x, y);
if (d1 < ans) query(tr[o].ls, x, y);
}
}
int main() {
tr[0].xmin = inf; tr[0].ymin = inf;
tr[0].xmax = -inf; tr[0].ymax = -inf;
n = read(); m = read();
for (int i = 1; i <= n; ++i) {
a[i].x = read(); a[i].y = read();
}
build(1, n, 1);
while (m--) {
int opt = read(); LL x = read(), y = read();
if (opt == 1) {
insert(1, x, y, 1);
a[sz].x = x; a[sz].y = y;
if (sz % base == 0) {
int tmp = sz; sz = 0;
build(1, tmp, 1);
}
}
else {
ans = inf;
query(1, x, y);
printf("%lld\n", ans);
}
}
return 0;
}
标签:SJY,return,rs,int,题解,LL,tr,棋子,ls 来源: https://www.cnblogs.com/little-aztl/p/14413218.html