题目:
题解:
喵喵喵一看题:这不是二维树状数组吗???然后一看数据范围N<=500000。。。。。
【其实这个题如果不是强制在线也可以用cdq分治做的】
这里有一个二维平面,我们就可以以点为节点组成一棵树!
本来想的是对于每一个要添加数字的点去添加数字,天哪那要好麻烦,还要记录有没有这个点,给每一个点加一个编号。。。我们可以把每一次添加当做添加一个新点,大不了就是一个重点,没有什么问题
为了保证效率,因为我们一开始建的树并不是一棵优美的KD-tree,所以不隔多久我们要重建一次,保证树的平衡性
至于qurry的过程思想上类似线段树,这一段在范围内就全部加入,不然就继续走分支
编码过程及其艰难,经过排查竟然有两处错误,一处手残,另一处是rebuild函数里一定要先把t[mid].l,t[mid].r设为0,因为ta都不一定有这棵子树了,后来肯定会错啊
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct hh{int d[2],l,r,mn[2],mx[2],sum,zz;}t[200005];
int cmpd,ans=0,x1,x2,y1,y2,root;
int cmp(const hh &a,const hh &b)
{
return (a.d[cmpd]<b.d[cmpd] || (a.d[cmpd]==b.d[cmpd] && a.d[!cmpd]<b.d[!cmpd]));
}
void updata(int now)
{
int lc=t[now].l,rc=t[now].r;
if (lc)
{
t[now].mn[0]=min(t[now].mn[0],t[lc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[lc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[lc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[lc].mx[1]);
}
if (rc)
{
t[now].mn[0]=min(t[now].mn[0],t[rc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[rc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[rc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[rc].mx[1]);
}
t[now].sum=t[lc].sum+t[rc].sum+t[now].zz;
}
int rebuild(int l,int r,int D)
{
cmpd=D;
int mid=(l+r)>>1;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];
t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];
t[mid].sum=t[mid].zz;
t[mid].l=t[mid].r=0; ////
if (l!=mid) t[mid].l=rebuild(l,mid-1,!D);
if (r!=mid) t[mid].r=rebuild(mid+1,r,!D);
updata(mid); return mid;
}
void insert(int now)
{
if (!root) {root=now; return;}
int p=root,D=0;
while (1)
{
if (t[now].mn[0]<t[p].mn[0]) t[p].mn[0]=t[now].mn[0];
if (t[now].mn[1]<t[p].mn[1]) t[p].mn[1]=t[now].mn[1];
if (t[now].mx[0]>t[p].mx[0]) t[p].mx[0]=t[now].mx[0];
if (t[now].mx[1]>t[p].mx[1]) t[p].mx[1]=t[now].mx[1];
t[p].sum+=t[now].sum;
if (t[now].d[D]<=t[p].d[D])
{
if (!t[p].l) {t[p].l=now; break;}
else p=t[p].l;
}
else
{
if (!t[p].r) {t[p].r=now; break;}
else p=t[p].r;
}
D=!D;
}
}
bool ok(int now)
{
return (t[now].d[0]>=x1 && t[now].d[1]>=y1 && t[now].d[0]<=x2 && t[now].d[1]<=y2);
}
int check(int now)//1-可以全部囊括,0-囊括部分,-1-无交集
{
if (t[now].mn[0]>=x1 && t[now].mn[1]>=y1 && t[now].mx[0]<=x2 && t[now].mx[1]<=y2) return 1;
if (t[now].mn[0]>x2 || t[now].mn[1]>y2 || t[now].mx[0]<x1 || t[now].mx[1]<y1) return -1;
return 0;
}
void qurry(int now)
{
if (ok(now)) ans+=t[now].zz;
if (t[now].l)
{
int bh=check(t[now].l);
if (bh==1) ans+=t[t[now].l].sum;
else if (bh==0) qurry(t[now].l);
}
if (t[now].r)
{
int bh=check(t[now].r);
if (bh==1) ans+=t[t[now].r].sum;
else if (bh==0) qurry(t[now].r);
}
}
int main()
{
int n,id,x,y,v;
scanf("%d",&n);n=0;
while (scanf("%d",&id))
{
if (id==3) break;
if (id==1)
{
scanf("%d%d%d",&x,&y,&v);
x^=ans; y^=ans; v^=ans;
n++;
t[n].mn[0]=t[n].mx[0]=t[n].d[0]=x;
t[n].mn[1]=t[n].mx[1]=t[n].d[1]=y;
t[n].zz=t[n].sum=v;
insert(n);
if (n%10000==0) root=rebuild(1,n,0);
}
if (id==2)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1^=ans; y1^=ans; x2^=ans; y2^=ans;
ans=0;
qurry(root);
printf("%d\n",ans);
}
}
}