KD-Tree

高维空间操作

例题

二维平面操作

#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int maxn=2e5+10,maxk=2;
const db e=0.75;//重构系数 
int n,lans;
int root,tot;
struct node{
	int l,r,u,d;//该点的子树x,y两维分别的区间 
	int sum,lc,rc,siz;
	int x,y,val;
	int pd;//从当前点切割的维数 
}t[maxn];
inline void pushup(int u){
	t[u].sum=t[t[u].lc].sum+t[t[u].rc].sum+t[u].val;
	t[u].siz=t[t[u].lc].siz+t[t[u].rc].siz+1;
	t[u].l=t[u].r=t[u].x;
	t[u].u=t[u].d=t[u].y;
	if(t[u].lc){
		t[u].l=min(t[u].l,t[t[u].lc].l),t[u].r=max(t[u].r,t[t[u].lc].r);
		t[u].d=min(t[u].d,t[t[u].lc].d),t[u].u=max(t[u].u,t[t[u].lc].u);
	}
	if(t[u].rc){
		t[u].l=min(t[u].l,t[t[u].rc].l),t[u].r=max(t[u].r,t[t[u].rc].r);
		t[u].d=min(t[u].d,t[t[u].rc].d),t[u].u=max(t[u].u,t[t[u].rc].u);
	}
}
inline bool reb(int u){//判断该点的某棵子树所占比例是否超过重构系数 
	return 1.0*max(t[t[u].lc].siz,t[t[u].rc].siz)>t[u].siz*e;
}
int g[maxn],num;
inline void in(int u){//重构第一步,先将该子树所有节点中序遍历存下来 
	if(!u) return;
	in(t[u].lc);
	g[++num]=u;
	in(t[u].rc);
}
inline bool cmpx(int x,int y){
	return t[x].x<t[y].x;
}
inline bool cmpy(int x,int y){
	return t[x].y<t[y].y;
}
inline void build(int &u,int l,int r){
	if(l>r){
		u=0;
		return;
	}
	
	db v1=0,v2=0,av1=0,av2=0; 
	for(int i=l;i<=r;i++) av1+=t[g[i]].x,av2+=t[g[i]].y;
	av1/=r-l+1,av2/=r-l+1;
	for(int i=l;i<=r;i++) v1+=(av1-t[g[i]].x)*(av1-t[g[i]].x),v2+=(av2-t[g[i]].y)*(av2-t[g[i]].y);
	//计算方差,选取离散程度大的一维切割 
	int mid=(l+r)>>1;
	if(v1>v2) nth_element(g+l,g+mid,g+r+1,cmpx),t[g[mid]].pd=1;
	else nth_element(g+l,g+mid,g+r+1,cmpy),t[g[mid]].pd=2;
	u=g[mid];
	build(t[u].lc,l,mid-1);
	build(t[u].rc,mid+1,r);
	pushup(u);
}
inline void rebuild(int &u){//重构 
	num=0;
	in(u);
	build(u,1,num);
}
inline void insert(int &u,int v){//插入 
	if(!u){
		u=v;
		pushup(u);
		return;
	}
	if(t[u].pd==1){
		if(t[v].x<=t[u].x) insert(t[u].lc,v);
		else insert(t[u].rc,v);
	}
	else{
		if(t[v].y<=t[u].y) insert(t[u].lc,v);
		else insert(t[u].rc,v);
	}
	pushup(u);
	if(reb(u)) rebuild(u); //若该点的某棵子树所占比例超过了重构系数就重构 
}
inline int qry(int x,int l,int r,int d,int u){
	if(!x||r<t[x].l||l>t[x].r||u<t[x].d||d>t[x].u) return 0;//该点不存在或者该点包含的子树完全不在所求矩阵内就直接返回0 
	if(l<=t[x].l&&r>=t[x].r&&d<=t[x].d&&u>=t[x].u) return t[x].sum;//该点包含的子树为所求矩阵的子矩阵 
	//该点的包含子树范围不全在所求矩阵内 
	int ans=0;
	if(l<=t[x].x&&r>=t[x].x&&d<=t[x].y&&u>=t[x].y) ans=t[x].val;//该点在所求矩阵内 
	return ans+qry(t[x].lc,l,r,d,u)+qry(t[x].rc,l,r,d,u);
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	while(1){
		int opt;
		cin>>opt;
		if(opt==3) break;
		if(opt==1){
			++tot;
			cin>>t[tot].x>>t[tot].y>>t[tot].val;
			t[tot].x^=lans;
			t[tot].y^=lans;
			t[tot].val^=lans;
			insert(root,tot);
		}
		else{
			int l,r,d,u;
			cin>>l>>d>>r>>u;
			l^=lans,r^=lans,d^=lans,u^=lans;
			lans=qry(root,l,r,d,u);
			cout<<lans<<'\n';
		}
	}
	return 0;
}
posted @ 2025-09-06 16:41  _dlwlrma  阅读(7)  评论(3)    收藏  举报