BJWC 2014 data problem solution

Topic portal

Main idea: give nnn points, there aremmm operations, each time: 1. Add a point; 2. Find the distance from the point closest to the query point in the point collection to the query point; 3. Find the distance from the point farthest from the query point to the query point in the query point collection.

answer

KD tree naked questions.

First maintain the matrix corresponding to each subtree.

The pruning to find the closest point is: first go to the matrix that is closer to the query point in the left and right subtrees.

Find the furthest pruning: similarly, go to the farthest matrix first.

code show as below:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 500010
#define inf 999999999
#define zuo ch[0]
#define you ch[1]
#define alpha 0.75

int n,m;
const int K=2;
struct point{
    
    int d[K];}q[maxn];
int dis(point x,point y){
    
    
	int re=0;
	for(int i=0;i<K;i++)re+=abs(x.d[i]-y.d[i]);
	return re;
}
int C;bool cmp(point x,point y){
    
    return x.d[C]<y.d[C];}
struct KD_node *root=NULL,*null=NULL;
struct KD_node{
    
    
	point x,ld,ru;
	KD_node *ch[2];
	int size;
	
	KD_node(point &X,int sz):x(X),ld(X),ru(X),size(sz){
    
    zuo=you=null;}
	KD_node(){
    
    }
	
	void check(){
    
    
		for(int i=0;i<K;i++){
    
    
			ld.d[i]=min(x.d[i],min(zuo->ld.d[i],you->ld.d[i]));
			ru.d[i]=max(x.d[i],max(zuo->ru.d[i],you->ru.d[i]));
		}
	}
	int dis_min(point &z){
    
    
		int re=0;
		for(int i=0;i<K;i++)
		if(z.d[i]<ld.d[i])re+=ld.d[i]-z.d[i];
		else if(z.d[i]>ru.d[i])re+=z.d[i]-ru.d[i];
		return re;
	}
	int dis_max(point &z){
    
    
		int re=0;
		for(int i=0;i<K;i++)
		re+=max(abs(z.d[i]-ld.d[i]),abs(z.d[i]-ru.d[i]));
		return re;
	}
};
void init(){
    
    
	null=new KD_node();null->size=0;
	for(int i=0;i<K;i++){
    
    
		null->ld.d[i]=inf;
		null->ru.d[i]=-inf;
	}
}
void build_KDtr(KD_node *&now,int l,int r,int CO=0)
{
    
    
	if(l>=r)return;
	int mid=l+r>>1;C=CO;
	nth_element(q+l,q+mid,q+r,cmp);
	now=new KD_node(q[mid],r-l);
	build_KDtr(now->zuo,l,mid,(CO+1)%K);
	build_KDtr(now->you,mid+1,r,(CO+1)%K);
	now->check();
}
void erase(KD_node *&now){
    
    
	if(now==null)return;
	q[++n]=now->x;
	erase(now->zuo);erase(now->you);
	delete now;
}
void rebuild(KD_node *&now){
    
    n=0;erase(now);build_KDtr(now,1,n+1);}
void add_node(KD_node *&now,point x,int CO=0,bool v=false)
{
    
    
	if(now==null){
    
    now=new KD_node(x,1);return;}
	now->size++;
	C=CO;int to=cmp(x,now->x)^1;
	bool tf=false;
	if(now->size*alpha<=now->ch[to]->size+1)tf=true;
	add_node(now->ch[to],x,(CO+1)%K,v|tf);
	if(!v&&tf)rebuild(now);
	now->check();
}
int ans;
void ask_min(KD_node *&now,point x)
{
    
    
	if(now==null)return;
	ans=min(ans,dis(now->x,x));
	int to=(now->zuo->dis_min(x)<now->you->dis_min(x))^1;
	ask_min(now->ch[to],x);
	if(now->ch[to^1]->dis_min(x)<ans)ask_min(now->ch[to^1],x);
}
void ask_max(KD_node *&now,point x)
{
    
    
	if(now==null)return;
	ans=max(ans,dis(now->x,x));
	int to=(now->zuo->dis_max(x)>now->you->dis_max(x))^1;
	ask_max(now->ch[to],x);
	if(now->ch[to^1]->dis_max(x)>ans)ask_max(now->ch[to^1],x);
}

int main()
{
    
    
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	for(int j=0;j<K;j++)scanf("%d",&q[i].d[j]);
	init();build_KDtr(root,1,n+1);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
    
    
		int id;point x;
		scanf("%d",&id);
		for(int j=0;j<K;j++)scanf("%d",&x.d[j]);
		switch(id){
    
    
			case 0:add_node(root,x);break;
			case 1:ans=2*inf;ask_min(root,x);printf("%d\n",ans);break;
			case 2:ans=-2*inf;ask_max(root,x);printf("%d\n",ans);break;
		}
	}
}

Guess you like

Origin blog.csdn.net/a_forever_dream/article/details/108024737