前言
K-d树的K其实表示的是数据是几维的,所以我们一般用的都是2-d树。
2-d树原理
当数据有两维时,一般都是维护平面上的数据,我们无法想线段树那样一直缩小范围得到想要的区间,但是我们可以通过交错缩小横纵坐标来最终得到想要的平面,这就是2-d树的原理。
写法:
例子:简单题
题目大意:动态维护矩形内数字和
和大多数树形结构一样,我们一切操作都需要从根开始,维护当前的点代表的平面,知道这个平面是询问的一个子平面,直接返回结果,否则继续向下递归,要特别注意的地方是需要特判当前的点是否在询问的平面的,如果是的话还要加上这个点的值。
#include
using namespace std;
const int maxm=2e5+1000;
const int inf=1e7;
int n,la,cntt;
bool nowp;
struct data
{
int num,sum,c[2],minx,miny,maxx,maxy,x,y;
friend bool operator < (data t1,data t2)
{
if(nowp) return t1.xelse return t1.ystruct kd_tree
{
data t[maxm];
int cnt,root;
void insert(int &now,int sx,int sy,int num1,int p)
{
if(sx==t[now].x&&sy==t[now].y)
{
t[now].num+=num1;
t[now].sum+=num1;
return;
}
if(!now)
{
now=++cnt;
if(!root) root=now;
t[now].num=t[now].sum=num1;
t[now].x=t[now].maxx=t[now].minx=sx;
t[now].y=t[now].maxy=t[now].miny=sy;
t[now].c[0]=t[now].c[1]=0;
return;
}
t[now].maxx=max(t[now].maxx,sx);
t[now].minx=min(t[now].minx,sx);
t[now].maxy=max(t[now].maxy,sy);
t[now].miny=min(t[now].miny,sy);
t[now].sum+=num1;
if(p)
{
if(sx<=t[now].x) insert(t[now].c[0],sx,sy,num1,!p);
else insert(t[now].c[1],sx,sy,num1,!p);
}
else
{
if(sy<=t[now].y) insert(t[now].c[0],sx,sy,num1,!p);
else insert(t[now].c[1],sx,sy,num1,!p);
}
}
int query(int now,int hx,int lx,int hy,int ly)
{
if(!now) return 0;
if(hxt[now].maxx||hyt[now].maxy) return 0;
if(t[now].maxx<=hx&&t[now].minx>=lx&&t[now].maxy<=hy&&t[now].miny>=ly) return t[now].sum;
int ans=0;
if(t[now].x>=lx&&t[now].x<=hx&&t[now].y>=ly&&t[now].y<=hy) ans+=t[now].num;
return ans+query(t[now].c[0],hx,lx,hy,ly)+query(t[now].c[1],hx,lx,hy,ly);
}
void rebuild(int &now,int l,int r,int p)
{
if(l>r) return;
nowp=p;
int mid=(l+r)>>1;
nth_element(t+l,t+mid+1,t+r+1);
now=mid;
if(!root) root=mid;
if(l==r)
{
t[mid].sum=t[mid].num;
t[mid].maxx=t[mid].minx=t[mid].x;
t[mid].maxy=t[mid].miny=t[mid].y;
t[mid].c[0]=t[mid].c[1]=0;
return;
}
rebuild(t[mid].c[0],l,mid-1,!p);
rebuild(t[mid].c[1],mid+1,r,!p);
t[mid].maxx=max(max(t[mid].c[0]?t[t[mid].c[0]].maxx:-inf,t[mid].c[1]?t[t[mid].c[1]].maxx:-inf),t[mid].x);
t[mid].maxy=max(max(t[mid].c[0]?t[t[mid].c[0]].maxy:-inf,t[mid].c[1]?t[t[mid].c[1]].maxy:-inf),t[mid].y);
t[mid].minx=min(min(t[mid].c[0]?t[t[mid].c[0]].minx:inf,t[mid].c[1]?t[t[mid].c[1]].minx:inf),t[mid].x);
t[mid].miny=min(min(t[mid].c[0]?t[t[mid].c[0]].miny:inf,t[mid].c[1]?t[t[mid].c[1]].miny:inf),t[mid].y);
t[mid].sum=t[t[mid].c[0]].sum+t[t[mid].c[1]].sum+t[mid].num;
}
void init()
{
root=0;
for(int i=0;i<=cnt;i++) t[i].maxx=t[i].minx=t[i].maxy=t[i].miny=t[i].c[0]=t[i].c[1]=t[i].sum=0;
}
}T;
int main()
{
scanf("%d",&n);
while(1)
{
cntt++;
if(cntt%10000==0)
{
T.init();
T.rebuild(n,1,T.cnt,1);
}
int type;
scanf("%d",&type);
if(type==1)
{
int x,y,num;
scanf("%d%d%d",&x,&y,&num);
x^=la;y^=la;num^=la;
T.insert(T.root,x,y,num,1);
}
else if(type==2)
{
int sx,sy,ex,ey;
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
sx^=la;sy^=la;ex^=la;ey^=la;
printf("%d\n",la=T.query(T.root,max(sx,ex),min(sx,ex),max(sy,ey),min(sy,ey)));
}
else break;
}
return 0;
}