Loading

P6224 [BJWC2014]数据 题解

明明是一道 \(\text{k-d tree}\) 模板题,为什么写的人这么少呢。

思路

看到平面上的操作,就必不可免的想到 \(\text{k-d tree}\)

\(\text{k-d tree}\) 板子大家应该都会写,这里讲一下最近最远的查询。

1.最远

我们可以发现,一个点到一个矩阵的最远距离一定是到其四个角的最大距离,\(\text{k-d tree}\) 维护的矩阵虽然不是一个实际的矩阵,但算出这个答案与原来的答案进行比较,也能剪枝掉不少情况。

2.最近

一个点到一个矩阵的最近距离我们发现,如果点在矩阵内,那么就是零,不然就是直接到边或者到四个角。

为了简便,我们可以这么写:

inline int ask(int x , int y , int id)
{
	int res = 0;
	res += max(0ll , y - t[id].u) + max(0ll , x - t[id].r);
	res += max(0ll , t[id].d - y) + max(0ll , t[id].l - x);
	return res;
}

本题实测是不需要方差建树和重构树的,直接交替建树就可以了。

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int N = 200020;
const int inf = 1e10;

int n , m , rt , cnt , top , ans , stk[N];

struct Node
{
	int l , r , u , d , siz , a[2] , son[2];
}t[N];

inline int read()
{
    int asd = 0 , qwe = 1; char zxc;
    while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
    while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
    return asd * qwe;
}

inline void push_up(int p)
{
	t[p].l = t[p].r = t[p].a[0] , t[p].u = t[p].d = t[p].a[1] , t[p].siz = 1;
	for(int i = 0;i <= 1;i++) if(t[p].son[i])
		t[p].siz += t[t[p].son[i]].siz,
   		t[p].l = min(t[p].l , t[t[p].son[i]].l) , t[p].r = max(t[p].r , t[t[p].son[i]].r),
   		t[p].d = min(t[p].d , t[t[p].son[i]].d) , t[p].u = max(t[p].u , t[t[p].son[i]].u);
}

inline void insert(int &p , int id , int opt)
{
	if(!p) { p = id , push_up(p); return; }
	if(t[id].a[opt] < t[p].a[opt]) insert(t[p].son[0] , id , opt ^ 1);
	else insert(t[p].son[1] , id , opt ^ 1); push_up(p);
}

inline void ask1(int p , int x , int y)
{
	ans = max(ans , abs(x - t[p].a[0]) + abs(y - t[p].a[1]));
	for(int i = 0;i <= 1;i++)
		if(t[p].son[i])
		{
			int l = t[p].l , r = t[p].r , u = t[p].u , d = t[p].d;
			int res = max({abs(l - x) + abs(u - y) , abs(r - x) + abs(u - y) , abs(r - x) + abs(d - y) , abs(l - x) + abs(d - y)});
			if(res > ans) ask1(t[p].son[i] , x , y);
		}
}

inline int ask(int x , int y , int id)
{
	int res = 0;
	res += max(0ll , y - t[id].u) + max(0ll , x - t[id].r);
	res += max(0ll , t[id].d - y) + max(0ll , t[id].l - x);
	return res;
}

inline void ask2(int p , int x , int y)
{
	ans = min(ans , abs(x - t[p].a[0]) + abs(y - t[p].a[1]));
	for(int i = 0;i <= 1;i++)
		if(t[p].son[i])
		{
			int res = ask(x , y , t[p].son[i]);
			if(res < ans) ask2(t[p].son[i] , x , y);
		}
}

signed main()
{
    n = read();
	for(int i = 1;i <= n;i++)
	{
		int x = read() , y = read(); ++cnt;
		t[cnt].a[0] = x , t[cnt].a[1] = y;
		insert(rt , cnt , 1);
	}
	m = read();
	for(int i = 1;i <= m;i++)
	{
		int opt = read() , x = read() , y = read();
		if(opt == 0)
		{
			t[++cnt].a[0] = x , t[cnt].a[1] = y;
			insert(rt , cnt , 1);
		}
		if(opt == 1) ans =  inf , ask2(rt , x , y) , printf("%lld\n" , ans);
		if(opt == 2) ans = -inf , ask1(rt , x , y) , printf("%lld\n" , ans);
	}
    return 0;
}

posted @ 2022-03-21 15:38  JiaY19  阅读(47)  评论(0编辑  收藏  举报