作用
维护 \(k\) 维空间上的点的数据结构,树高严格 \(log\),空间 \(O(n)\)。支持插入,并如替罪羊树一般根据“不平衡度” \(\alpha\) 重构。
可以用线段树式或平衡树式实现。
建树
对于一个给定序列,类似线段树建树,使用 nth_element
可以总复杂度 \(n\log\) 建树。
由于需要分割,要么轮流按顺序维度分割,要么按方差较大的一位分(小优化?)。
修改
单点加入
一路走到叶子,类似替罪羊的拍平。可以 \(\alpha=0.6\)。
区间修改
类似线段树,可以打标记,写 pushdown
。
删除节点
打标记,同时维护子树 size
(未删点数),便于重构。
查询
核心是分成不交、完全计入贡献、部分有(继续递归)三个部分,类似线段树,但是复杂度玄学。
为了判断某个子树有没有进去的价值,需要 pushup
出子树内各个坐标的最值,便于判断在不在查询范围内/可能使答案更优。
代码
(杂交了一下)
带修
inline int New(node x){
int u=hh?rub[hh--]:++tot;
tr[u].val=x;
tr[u].siz=1;
tr[u].mn[0]=tr[u].mx[0]=x.px[0];
tr[u].mn[1]=tr[u].mx[1]=x.px[1];
tr[u].ls=tr[u].rs=0;
return u;
}
inline void pushup(int u){
int ls=tr[u].ls,rs=tr[u].rs;
tr[u].siz=tr[ls].siz+tr[rs].siz+1;
for(int i=0;i<K;++i){
tr[u].mn[i]=tr[u].mx[i]=tr[u].val.px[i];
if(ls){
tr[u].mn[i]=min(tr[u].mn[i],tr[ls].mn[i]);
tr[u].mx[i]=max(tr[u].mx[i],tr[ls].mx[i]);
}
if(rs){
tr[u].mn[i]=min(tr[u].mn[i],tr[rs].mn[i]);
tr[u].mx[i]=max(tr[u].mx[i],tr[rs].mx[i]);
}
}
}
inline int build(int l,int r,int d){
int mid=l+r>>1;
dm=d;
nth_element(a+l,a+mid,a+r+1,cmp);
int u=New(a[mid]);
if(l<mid) tr[u].ls=build(l,mid-1,d^1);
if(r>mid) tr[u].rs=build(mid+1,r,d^1);
pushup(u);
return u;
}
inline void pia(int u){
if(tr[u].ls) pia(tr[u].ls);
a[++num]=tr[u].val;
if(tr[u].rs) pia(tr[u].rs);
rub[++hh]=u;
}
inline void check(int &u,int d){
if(tr[u].siz>3&&max(tr[tr[u].ls].siz,tr[tr[u].rs].siz)*5>tr[u].siz*3){
num=0;pia(u);
u=build(1,num,d);
}
}
inline void insert(int &u,int d){
if(!u){
u=New(tx);
return ;
}
if(tx.px[d]<=tr[u].val.px[d]) insert(tr[u].ls,d^1);
else insert(tr[u].rs,d^1);
pushup(u);check(u,d);
}
不带
inline void pushup(int u){
int ls=tr[u].ls,rs=tr[u].rs;
for(int i=0;i<K;++i){
tr[u].mn[i]=tr[u].mx[i]=c[u].px[i];
if(ls){
tr[u].mn[i]=min(tr[u].mn[i],tr[ls].mn[i]);
tr[u].mx[i]=max(tr[u].mx[i],tr[ls].mx[i]);
}
if(rs){
tr[u].mn[i]=min(tr[u].mn[i],tr[rs].mn[i]);
tr[u].mx[i]=max(tr[u].mx[i],tr[rs].mx[i]);
}
}
}
inline int build(int l,int r,int d){
int mid=l+r>>1;
nth_element(b+l,b+mid,b+r+1,[&](int x,int y){return c[x].px[d]<c[y].px[d];});
int u=b[mid];
if(l<mid) tr[u].ls=build(l,mid-1,d^1);
if(mid<r) tr[u].rs=build(mid+1,r,d^1);
pushup(u);
return u;
}
模型
k近点对。
tips
下次学一下历史最大值。
标签:rs,int,siz,tr,Tree,ls,inline From: https://www.cnblogs.com/mRXxy0o0/p/18000606