Description
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 | 参数限制 | 内容 |
1 x y A | 1<=x,y<=N,A是正整数 | 将格子x,y里的数字加上A |
2 x1 y1 x2 y2 | 1<=x1<= x2<=N 1<=y1<= y2<=N | 输出x1 y1 x2 y2这个矩形内的数字和 |
3 | 无 | 终止程序 |
Input
输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3
Sample Output
3
5
5
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
样例解释见OJ2683
新加数据一组,但未重测----2015.05.24
神TM加一组数据但未重测。特意加了一组卡不重构人的数据
kd-tree板子题,直接维护即可
重构的话我没用那种标准版的替罪羊树重构
设置了一个阀值,点数每次大于这个阀值的k倍就暴力重构一次
总觉得这么做有点不科学
----------------------------------------------------------------------------------------
各种被卡调了整整三天,一开始先弄了个动态加点的二维树套树,结果空间爆炸
各种姿势写kd-tree各种挂
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree
{
int min[2],max[2],p[2];
int ll,rr;
int s,x;
}tr[200001];
int tot;
int cmpd,rt;
inline bool cmp(tree x,tree y)
{
return x.p[cmpd]<y.p[cmpd]||x.p[cmpd]==y.p[cmpd]&&x.p[!cmpd]<y.p[!cmpd];
}
inline int min(int x,int y)
{
if(x<y)
return x;
return y;
}
inline int max(int x,int y)
{
if(x>y)
return x;
return y;
}
inline void up(int p)
{
int L=tr[p].ll,R=tr[p].rr;
if(L!=0)
{
tr[p].min[0]=min(tr[L].min[0],tr[p].min[0]);
tr[p].min[1]=min(tr[L].min[1],tr[p].min[1]);
tr[p].max[0]=max(tr[L].max[0],tr[p].max[0]);
tr[p].max[1]=max(tr[L].max[1],tr[p].max[1]);
}
if(R!=0)
{
tr[p].min[0]=min(tr[R].min[0],tr[p].min[0]);
tr[p].min[1]=min(tr[R].min[1],tr[p].min[1]);
tr[p].max[0]=max(tr[R].max[0],tr[p].max[0]);
tr[p].max[1]=max(tr[R].max[1],tr[p].max[1]);
}
tr[p].s=tr[L].s+tr[R].s+tr[p].x;
}
inline int build(int l,int r,int d)
{
int mid=(l+r)/2;
cmpd=d;
nth_element(tr+l,tr+mid,tr+r+1,cmp);
tr[mid].min[0]=tr[mid].p[0];
tr[mid].min[1]=tr[mid].p[1];
tr[mid].max[0]=tr[mid].p[0];
tr[mid].max[1]=tr[mid].p[1];
// tr[mid].s=0;
if(l<mid)
tr[mid].ll=build(l,mid-1,!d);
else
tr[mid].ll=0;
if(r>mid)
tr[mid].rr=build(mid+1,r,!d);
else
tr[mid].rr=0;
up(mid);
return mid;
}
int x1[2];
inline int add(int p,int x,int y,int d,int xx)
{
if(p==0)
{
tot++;
tr[tot].min[0]=tr[tot].max[0]=tr[tot].p[0]=x;
tr[tot].min[1]=tr[tot].max[1]=tr[tot].p[1]=y;
tr[tot].s=xx;
tr[tot].x=xx;
return tot;
}
if(tr[p].p[0]==x&&tr[p].p[1]==y)
{
tr[p].s+=xx;
tr[p].x+=xx;
return p;
}
x1[0]=x;
x1[1]=y;
if(x<tr[p].min[0])
tr[p].min[0]=x;
else if(x>tr[p].max[0])
tr[p].max[0]=x;
if(y<tr[p].min[1])
tr[p].min[1]=y;
else if(y>tr[p].max[1])
tr[p].max[1]=y;
if(x1[d]<=tr[p].p[d])
tr[p].ll=add(tr[p].ll,x1[0],x1[1],!d,xx);
else
tr[p].rr=add(tr[p].rr,x1[0],x1[1],!d,xx);
up(p);
return p;
}
inline int ask(int p,int xx1,int yy1,int xx2,int yy2,int d)
{
if(tr[p].s==0||p==0)
return 0;
if(xx1<=tr[p].min[0]&&yy1<=tr[p].min[1]&&tr[p].max[0]<=xx2&&tr[p].max[1]<=yy2)
return tr[p].s;
int x1[2],x2[2];
x1[0]=xx1;
x1[1]=yy1;
x2[0]=xx2;
x2[1]=yy2;
int L=tr[p].ll,R=tr[p].rr;
int ans=0;
if(xx1<=tr[p].p[0]&&tr[p].p[0]<=xx2&&yy1<=tr[p].p[1]&&tr[p].p[1]<=yy2)
ans+=tr[p].x;
if(L&&tr[L].max[0]>=x1[0]&&tr[L].min[0]<=x2[0]&&tr[L].max[1]>=x1[1]&&tr[L].min[1]<=x2[1])
if(x1[d]<=tr[p].p[d])
ans+=ask(L,xx1,yy1,xx2,yy2,!d);
if(R&&tr[R].max[0]>=x1[0]&&tr[R].min[0]<=x2[0]&&tr[R].max[1]>=x1[1]&&tr[R].min[1]<=x2[1])
if(x2[d]>=tr[p].p[d])
ans+=ask(R,xx1,yy1,xx2,yy2,!d);
return ans;
}
inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
struct quest
{
int x;
int x1,y1,x2,y2;
int xx;
}xt[200001];
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int n;
n=read();
int x;
int x1,y1,x2,y2;
n=0;
int m=0;
x=read();
int rt=0;
tot=0;
int last_ans=0;
while(x!=3)
{
if(x==1)
{
m++;
xt[m].x=x;
xt[m].x1=read();
xt[m].y1=read();
xt[m].x2=read();
}
else
{
m++;
xt[m].x=x;
xt[m].x1=read();
xt[m].y1=read();
xt[m].x2=read();
xt[m].y2=read();
n++;
}
scanf("%d",&x);
}
int nt=(int)sqrt((double)n*log2((double)n))+1,i;
nt*=2;
for(i=1;i<=m;i++)
{
if(xt[i].x==1)
{
x1=xt[i].x1^last_ans;
y1=xt[i].y1^last_ans;
x2=xt[i].x2^last_ans;
add(rt,x1,y1,0,x2);
if(rt==0)
rt=1;
if(nt!=0&&tot%nt==0)
rt=build(1,tot,0);
}
else
{
x1=xt[i].x1^last_ans;
y1=xt[i].y1^last_ans;
x2=xt[i].x2^last_ans;
y2=xt[i].y2^last_ans;
last_ans=ask(rt,x1,y1,x2,y2,0);
printf("%d\n",last_ans);
}
//last_ans=0;
}
return 0;
}