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。
接下来每行一个操作。
Output
对于每个2操作,输出一个对应的答案。
Sample Input
4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
HINT
1<=N<=500000,操作数不超过200000个,内存限制20M。
对于100%的数据,操作1中的A不超过2000。
分析:一道模版的k-d tree,结果空间卡得太紧了,反正洛谷过不了,于是就跑到bzoj上交。
k-d tree反正每次就是把宽度最大的切一半,这题要动态开点,我觉得不动态也能过。
代码:
/**************************************************************
Problem: 2683
User: beginend
Language: C++
Result: Accepted
Time:45488 ms
Memory:71604 kb
****************************************************************/
#include <iostream>
#include <cstdio>
using namespace std;
struct node{
int s,lc,rc;
}t[6000001];
int n,i,cnt;
int op,l,r,x,y,w,last_ans,root;
void change(int &p,int x,int y,int k,int ll,int rr,int xx,int yy)
{
if (p==0)
{
cnt++;
p=cnt;
}
if ((x==ll) && (x==rr) && (y==xx) && (y==yy))
{
t[p].s+=k;
return;
}
if (yy-xx>rr-ll)
{
int mid=(xx+yy)/2;
if (y<=mid) change(t[p].lc,x,y,k,ll,rr,xx,mid);
else change(t[p].rc,x,y,k,ll,rr,mid+1,yy);
t[p].s=t[t[p].lc].s+t[t[p].rc].s;
}
else
{
int mid=(ll+rr)/2;
if (x<=mid) change(t[p].lc,x,y,k,ll,mid,xx,yy);
else change(t[p].rc,x,y,k,mid+1,rr,xx,yy);
t[p].s=t[t[p].lc].s+t[t[p].rc].s;
}
}
int getsum(int p,int l,int r,int x,int y,int ll,int rr,int xx,int yy)
{
if (p==0) return 0;
if ((ll==l) && (rr==r) && (xx==x) && (yy==y)) return t[p].s;
if (yy-xx>rr-ll)
{
int mid=(xx+yy)/2;
if (y<=mid) return getsum(t[p].lc,l,r,x,y,ll,rr,xx,mid);
else
{
if (x>mid) return getsum(t[p].rc,l,r,x,y,ll,rr,mid+1,yy);
else
return getsum(t[p].lc,l,r,x,mid,ll,rr,xx,mid)
+getsum(t[p].rc,l,r,mid+1,y,ll,rr,mid+1,yy);
}
}
else
{
int mid=(ll+rr)/2;
if (r<=mid) return getsum(t[p].lc,l,r,x,y,ll,mid,xx,yy);
else
{
if (l>mid) return getsum(t[p].rc,l,r,x,y,mid+1,rr,xx,yy);
else
return getsum(t[p].lc,l,mid,x,y,ll,mid,xx,yy)
+getsum(t[p].rc,mid+1,r,x,y,mid+1,rr,xx,yy);
}
}
}
int main()
{
scanf("%d",&n);
scanf("%d",&op);
last_ans=0;
while (op!=3)
{
if (op==1)
{
scanf("%d%d%d",&x,&y,&w);
//x^=last_ans;
//y^=last_ans;
//w^=last_ans;
change(root,x,y,w,1,n,1,n);
}
else
{
scanf("%d%d%d%d",&l,&r,&x,&y);
//l^=last_ans;
//r^=last_ans;
//x^=last_ans;
//y^=last_ans;
last_ans=getsum(root,l,x,r,y,1,n,1,n);
printf("%d\n",last_ans);
}
scanf("%d",&op);
}
return 0;
}