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;
}

posted @ 2021-02-18 19:30  蓝田日暖玉生烟  阅读(76)  评论(0编辑  收藏  举报