k-d tree P2479 求调
  • 板块灌水区
  • 楼主ShiRoZeTsuHL卜奎BBQ!
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/12/5 12:55
  • 上次更新2023/12/5 16:55:56
查看原帖
k-d tree P2479 求调
678858
ShiRoZeTsuHL卜奎BBQ!楼主2023/12/5 12:55

大意:给定 nn 个点,请找出一个点,使得这个点与其它所有点的曼哈顿距离的最大值与最小值之差最小。

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 1e5 + 5;
const int inf = 2147483647;

int n, rt, ansx, ansy, ans = inf;
int g[maxn];

struct node {
	int ls, rs;
	int x[2], L[2], R[2];
} t[maxn];

#define mid ((l + r) >> 1)

struct KDT {
	void pushup(int o) {
		for(int i = 0; i <= 1; i++) {
			t[o].L[i] = t[o].R[i] = t[o].x[i];
			if(t[o].ls) {
				t[o].L[i] = min(t[o].L[i], t[t[o].ls].L[i]);
				t[o].R[i] = max(t[o].R[i], t[t[o].ls].R[i]);
			}
			if(t[o].rs) {
				t[o].L[i] = min(t[o].L[i], t[t[o].rs].L[i]);
				t[o].R[i] = max(t[o].R[i], t[t[o].rs].R[i]);
			}
		}
	}

	int build(int l, int r, int d) {
		nth_element(g+l, g+mid, g+r+1, [&](int a, int b) {
			return t[a].x[d] < t[b].x[d];
		}) ;
		int o = g[mid];
		if(l < mid) t[o].ls = build(l, mid-1, d^1);
		if(mid < r) t[o].rs = build(mid+1, r, d^1);
		pushup(o);
		return o;
	}

	int f(int x, int y, int lx, int ly, int rx, int ry) {
		return (x<lx ? lx-x : (x>rx ? x-rx : 0) + (y<ly ? ly-y : (y>ry ? y-ry : 0)));
	}

	void query1(int o, int x) {
		if(!o) return;
		if(f(t[x].x[0], t[x].x[1], t[o].L[0], t[o].L[1], t[o].R[0], t[o].R[1]) > ansx) return;
		if(t[o].x[0] != t[x].x[0] || t[o].x[1] != t[x].x[1]) 
			ansx = min(ansx, f(t[x].x[0], t[x].x[1], t[o].x[0], t[o].x[1], t[o].x[0], t[o].x[1]));
		int a = t[o].ls ? f(t[x].x[0], t[x].x[1], t[t[o].ls].L[0], t[t[o].ls].L[1], t[t[o].ls].R[0], t[t[o].ls].R[1]) : inf;
		int b = t[o].rs ? f(t[x].x[0], t[x].x[1], t[t[o].rs].L[0], t[t[o].rs].L[1], t[t[o].rs].R[0], t[t[o].rs].R[1]) : inf;
		if(a <= b) query1(t[o].ls, x), query1(t[o].rs, x);
		else query1(t[o].rs, x), query1(t[o].ls, x);
	}

	int h(int x, int y, int lx, int ly, int rx, int ry) {
		return max(abs(x-lx), abs(x-rx)) + max(abs(y-ly), abs(y-ry));
	}

	void query2(int o, int x) {
		if(!o) return;
		if(h(t[x].x[0], t[x].x[1], t[o].L[0], t[o].L[1], t[o].R[0], t[o].R[1]) < ansy) return;
		ansy = max(ansy, h(t[x].x[0], t[x].x[1], t[o].x[0], t[o].x[1], t[o].x[0], t[o].x[1]));
		int a = t[o].ls ? h(t[x].x[0], t[x].x[1], t[t[o].ls].L[0], t[t[o].ls].L[1], t[t[o].ls].R[0], t[t[o].ls].R[1]) : -inf;
		int b = t[o].rs ? h(t[x].x[0], t[x].x[1], t[t[o].rs].L[0], t[t[o].rs].L[1], t[t[o].rs].R[0], t[t[o].rs].R[1]) : -inf;
		if(a >= b) query2(t[o].ls, x), query2(t[o].rs, x);
		else query2(t[o].rs, x), query2(t[o].ls, x);
	}
} kdt;

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		scanf("%d %d", &t[i].x[0], &t[i].x[1]);
		g[i] = i;
	}
	rt = kdt.build(1, n, 0);

	for(int i = 1; i <= n; i++) {
		ansx = inf, ansy = 0;
		kdt.query1(rt, i); kdt.query2(rt, i);
		ans = min(ans, ansy - ansx);
	}
	printf("%d\n", ans);
	return 0;
}

一直 10pts,不太清楚是什么原因

2023/12/5 12:55
加载中...