NKOJ 3702 打鼹鼠


问题描述

在这个“打鼹鼠”的游戏中,鼹鼠会不时地从洞中钻出来,不过不会从洞口钻进去。洞口都在一个大小为n(n<=1024)的正方形中。这个正方形在一个平面直角坐标系中,左下角为(0,0),右上角为(n-1,n-1)。洞口所在的位置都是整点,就是横纵坐标都为整数的点。
一个玩家不时地会想知道某一个范围的鼹鼠总数。请你快速回答。


输入格式

输入有若干行:
第一行,一个数n,表示鼹鼠的范围。
以后每一行开头都有一个数m,表示不同的操作:
m=1,那么后面跟着3个数x,y,k,表示在点(x,y)处新出现了k只鼹鼠;
m=2,那么后面跟着4个数x1,y1,x2,y2表示询问矩形(x1,y1)-(x2,y2)内的鼹鼠数量;
m=3,表示游戏结束,不能玩了。保证这个数会在输入的最后一行。
询问数不会超过10000,鼹鼠数不会超过maxlongint。


输出格式

对于每个m=2,输出一行数,这行数只有一个数,即所询问的区域内鼹鼠的个数。


样例输入

4
1 2 2 5
2 0 0 2 3
3


样例输出

5

第一次用二维树状数组orz
犯了一个低级错误 modify(x.y)时,因为可以考虑原点,所以说当x==0或者y==0时,就会让modify函数陷入死循环==
然后我就T了很多次orz 该打
好了进入正题
这道题实际上运用了一个二维树状数组
至于改动的函数
int getsum(int x,int y)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
for(int j=y;j>0;j-=lowbit(j))sum+=c[i][j];
return sum;
}
void modify(int x,int y,int z)
{
int i,j;
for(i=x;i<=n;i+=lowbit(i))
for(j=y;j<=n;j+=lowbit(j))
c[i][j]+=z;
}
通过此道理,空间里面的坐标也可以处理了,通过二维数组可以推广到n维数组(当然要在题目要求的范围的)
回到题目,要求某个区域里面的sum,就用大的正方形减去两个长方形再加上多减的那个小矩形就可以了,和平面直角坐标系中求面积是同样的道理,所以说最后要求的就是下面这坨东西
getsum(a,b)+getsum(c+1,d+1)-getsum(a,d+1)-getsum(c+1,b);

附上代码:

#include
using namespace std; 
long long C[1030][1030],n,m,x,y,z,a,b,c,d; 
int lowbit(int x){return x&-x;}
void modify(int x,int y,int z) 
{ 
    int i,j; 
    for(i=x;i<=n;i+=lowbit(i)) 
    for(j=y;j<=n;j+=lowbit(j))
    C[i][j]+=z;
} 
int getsum(int x,int y) 
{ 
    int sum=0; 
    for(int i=x;i>0;i-=lowbit(i)) 
    for(int j=y;j>0;j-=lowbit(j))sum+=C[i][j]; 
    return sum; 
} 
int main() 
{ 
    cin>>n; 
    while(1) 
    { 
        cin>>m; 
        if(m==3)break; 
        if(m==1) 
        { 
            cin>>x>>y>>z;
            modify(x+1,y+1,z); 
        } 
        if(m==2) 
        { 
            cin>>a>>b>>c>>d;
            cout<1,d+1)-getsum(a,d+1)-getsum(c+1,b)<

你可能感兴趣的:(树状数组)