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
Sample Output
3
5
HINT
数据规模和约定
1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。
样例解释见OJ2683
新加数据一组,但未重测—-2015.05.24
Source
By wjy1998
补了一波kdtree,发现这是个好东西
当成平衡树或者线段树就行了
4066因为是动态加点的,所以需要隔一些点暴力重构一次
点插入,矩阵求和,裸做
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 200010
#define Dnum 2
#define GET (ch>='0'&&ch<='9')
using namespace std;
int cnt,n,Q,root=1,ans,dx1,dx2,dy1,dy2;
bool cmp_d;
struct Query { int opt,X1,Y1,X2,Y2,val; }q[MAXN];
inline int in(int &x)
{
char ch=getchar();x=0;
while (!GET) ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();return x;
}
struct KDtree
{
int ch[2],w,sum,minn[Dnum],maxn[Dnum],d[Dnum];
inline void init() { for (int i=0;i<Dnum;++i) minn[i]=maxn[i]=d[i]; sum=w; }
inline bool operator < (const KDtree& a)const { return d[cmp_d]<a.d[cmp_d]; }
}tree[MAXN];
inline void push_up(int rt)
{
tree[rt].sum=tree[rt].w;
for (int i=0;i<Dnum;++i)
if (tree[rt].ch[i])
{
int x=tree[rt].ch[i];
tree[rt].sum+=tree[x].sum;
for (int j=0;j<Dnum;++j)
tree[rt].minn[j]=min(tree[rt].minn[j],tree[x].minn[j]),
tree[rt].maxn[j]=max(tree[rt].maxn[j],tree[x].maxn[j]);
}
}
int rebuild(int l=1,int r=n,bool d=0)
{
cmp_d=d;int mid=(l+r)>>1;nth_element(tree+l,tree+mid,tree+r+1);
tree[mid].init();
if (l!=mid) tree[mid].ch[0]=rebuild(l,mid-1,d^1);
if (r!=mid) tree[mid].ch[1]=rebuild(mid+1,r,d^1);
return push_up(mid),mid;
}
void insert(int rt=root,bool d=0)
{
bool flag=(tree[n].d[d]>tree[rt].d[d]);
if (tree[rt].ch[flag]) insert(tree[rt].ch[flag],d^1); else tree[rt].ch[flag]=n;
push_up(rt);
}
void query(int rt=root)
{
if (tree[rt].d[0]>=dx1&&tree[rt].d[0]<=dx2&&tree[rt].d[1]>=dy1&&tree[rt].d[1]<=dy2) ans+=tree[rt].w;
for (int i=0;i<Dnum;++i)
if (tree[rt].ch[i])
{
int x=tree[rt].ch[i];
if (tree[x].maxn[0]>=dx1&&tree[x].maxn[1]>=dy1&&tree[x].minn[0]<=dx2&&tree[x].minn[1]<=dy2)
{
if (tree[x].minn[0]>=dx1&&tree[x].maxn[0]<=dx2&&tree[x].minn[1]>=dy1&&tree[x].maxn[1]<=dy2) ans+=tree[x].sum;
else query(x);
}
}
}
int main()
{
in(n);n=0;
while (in(q[++Q].opt)!=3)
{
if (q[Q].opt==1) in(q[Q].X1),in(q[Q].Y1),in(q[Q].val),++n;
else in(q[Q].X1),in(q[Q].Y1),in(q[Q].X2),in(q[Q].Y2);
}
int size=(int)sqrt((double)n*log2((double)n));Q--;n=0;
for (int i=1;i<=Q;i++)
{
if (q[i].opt==1)
{
++n;tree[n].d[0]=q[i].X1^ans;tree[n].d[1]=q[i].Y1^ans;tree[n].w=q[i].val^ans;
tree[n].init();
if (n>1) insert();
if (size==1||size==0||n%size==0)
{
for (int j=1;j<=n;++j) tree[j].ch[0]=tree[j].ch[1]=0;
rebuild();root=(1+n)>>1;
}
}
else
{
dx1=q[i].X1^ans;dx2=q[i].X2^ans;dy1=q[i].Y1^ans;dy2=q[i].Y2^ans;ans=0;
if (n) query();printf("%d\n",ans);
}
}
}