您的位置:首页 > 其它

POJ 1195 Mobile phones——二维树状数组

2014-07-30 10:17 309 查看
题意:在一个大小为s*s的矩阵中,每一个单位格子上可能放着多部手机。手机数目可能增加或者减少。输入数据给一些手机增减的信息。然后对于每一个询问,给出询问范围内的手机数量。

思路:求二维数组内某一个矩阵的元素和。由于求和次数很多,如果用普通的数组方法时间复杂度O(n*n)会超时。应利用树状数组来解。

关于二维树状数组求区间和的公式推导 A(x,y)



如上图 A(x,y),B(x1,y1)。求图中蓝色面积。

我们知道二维树状数组的sum都是以从原点(这里原点是(1,1,))到改点的线段为对角线的矩形。因此求图中蓝色面积S,说白了,就是几个矩形面积减来减去减多了再加上,凑来凑去求面积。显然 s=s(x,y)-s(x,y1)-s(x1,y) + s(x1,y1) (就是大矩形-(橙色矩形+绿色矩形)*2+绿色矩形)。有了这个公式,便可计算蓝色区域面积了。因为矩形中存储的相当于是元素值,求得了面积,也即求得了sum。

AC代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define ll long long
using namespace std;
const int MAX=1<<28;
ll c[1500][1500],n;
int lowbit(int x)
{
    return x&(-x);
}
void updata(int x,int y,int dt)
{
    int i,j;
    for(i=x; i<=n+1;i+=lowbit(i))
        for(j=y; j<=n+1; j+=lowbit(j))
            c[i][j]+=dt;
}
ll sum(int x,int y)
{
    ll ans=0;
    for(int i=x; i>0; i-=lowbit(i))
        for(int j=y; j>0; j-=lowbit(j))
            ans+=c[i][j];
    return ans;
}

int main()
{
    int ty,x,y,x1,y1,val;
    memset(c,0,sizeof(c));
    while(scanf("%d",&ty))
    {
       if(ty==3) break;
       else if(ty==0) scanf("%d",&n);
       else if(ty==1)
       {
           scanf("%d%d%d",&x,&y,&val);
           updata(x+1,y+1,val);
       }
       else if(ty==2)
       {
           scanf("%d%d%d%d",&x1,&y1,&x,&y);
           ll ans=0;
           x++,y++;
           ans=sum(x,y)-sum(x1,y)-sum(x,y1)+sum(x1,y1);
           printf("%lld\n",ans);
       }
    }
    return 0;
}


+
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: