Solución de problemas de datos de BJWC 2014

Portal de temas

Idea principal: dar nnn puntos, haymmm operaciones, cada vez: 1. Agregar un punto; 2. Encontrar la distancia desde el punto más cercano al punto de consulta en la colección de puntos hasta el punto de consulta; 3. Encontrar la distancia desde el punto más lejano desde el punto de consulta hasta el punto de consulta en la colección de puntos de consulta.

responder

Preguntas desnudas del árbol KD.

Primero mantenga la matriz correspondiente a cada subárbol.

La poda para encontrar el punto más cercano es: primero vaya a la matriz que está más cerca del punto de consulta en los subárboles izquierdo y derecho.

Encuentre la poda más lejana: de manera similar, vaya primero a la matriz más lejana.

el código se muestra a continuación:

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

Supongo que te gusta

Origin blog.csdn.net/a_forever_dream/article/details/108024737
Recomendado
Clasificación