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

浙公网安备 33010602011771号