KDtree模板题

不会的看这里

本题离线的话就是裸的cdq分治

强制在线那就按维分割,加入新点的话类似于建树过程,同时记录一下点的范围,以便询问的时候好剪枝

为了防止出题人毒瘤(比如让你建的树成了一条链),你可以每过一段时间重构一下这棵树。

代码虽长,但很好写

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int d,root;
const int N=490001;
struct data
{
    int p[2],maxn[2],minn[2],c[2],w,sum;
}a[N];
bool cmp(data a,data b)
{
    return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];
}
void pushup(int k,int s)
{
    a[k].maxn[0]=max(a[k].maxn[0],a[s].maxn[0]);
    a[k].minn[0]=min(a[k].minn[0],a[s].minn[0]);
    a[k].maxn[1]=max(a[k].maxn[1],a[s].maxn[1]);
    a[k].minn[1]=min(a[k].minn[1],a[s].minn[1]);
    a[k].sum+=a[s].sum;
}
int build(int l,int r,int now)
{
	int mid=(l+r)>>1;d=now;
	nth_element(a+l,a+mid,a+1+r,cmp);
	a[mid].maxn[0]=a[mid].minn[0]=a[mid].p[0];
	a[mid].maxn[1]=a[mid].minn[1]=a[mid].p[1];
	a[mid].sum=a[mid].w;
	a[mid].c[0]=a[mid].c[1]=0;
	if(l<mid)a[mid].c[0]=build(l,mid-1,now^1),pushup(mid,a[mid].c[0]);
    if(r>mid)a[mid].c[1]=build(mid+1,r,now^1),pushup(mid,a[mid].c[1]);
    return mid;
}
void Insert(int x)
{
	int *t=&root;d=0;
	while(*t)pushup(*t,x),t=&a[*t].c[a[x].p[d]>a[*t].p[d]],d^=1;
	*t=x;
}
int query(int k,int x1,int y1,int x2,int y2)
{
    if(!k||a[k].maxn[0]<x1||x2<a[k].minn[0]||a[k].maxn[1]<y1||y2<a[k].minn[1])return 0;
    if(x1<=a[k].minn[0]&&a[k].maxn[0]<=x2&&y1<=a[k].minn[1]&&a[k].maxn[1]<=y2)return a[k].sum;
    int ans=0;
    if(x1<=a[k].p[0]&&a[k].p[0]<=x2&&y1<=a[k].p[1]&&a[k].p[1]<=y2)ans+=a[k].w;
    ans+=query(a[k].c[0],x1,y1,x2,y2)+query(a[k].c[1],x1,y1,x2,y2);
    return ans;
}
int main()
{
	int opt,x1,y1,x2,y2,last=0,tot=0;
	scanf("%*d");
	while(scanf("%d",&opt)!=EOF&&opt!=3)
	{
		if(opt==1)
		{
			++tot,scanf("%d%d%d",&a[tot].p[0],&a[tot].p[1],&a[tot].w);
            a[tot].p[0]^=last,a[tot].p[1]^=last,a[tot].w^=last,a[tot].sum=a[tot].w;
            a[tot].maxn[0]=a[tot].minn[0]=a[tot].p[0];
            a[tot].maxn[1]=a[tot].minn[1]=a[tot].p[1];
            Insert(tot);
            if(tot%10000==0)root=build(1,tot,0);
		}
		else scanf("%d%d%d%d",&x1,&y1,&x2,&y2),x1^=last,y1^=last,x2^=last,y2^=last,printf("%d\n",last=query(root,x1,y1,x2,y2));
	}
	return 0;
}