题意:
动态单点更新和查询区域和。
分析:
裸的二维树状数组,不过我用一维的暴力3600+ms过了,罪过。。之后也附上别人二维树状数组的正确做法吧。
代码:
一维暴力解法:
//poj 1195
//sep9
#include <iostream>
using namespace std;
const int maxN=1024+10;
struct BIT
{
int c[maxN],n;
int lowbit(int x)
{
return x&(x^(x-1));
}
void modify(int i,int d)
{
while(i<=n){
c[i]+=d;
i+=lowbit(i);
}
}
int q(int i)
{
int sum;
for(sum=0;i>0;i-=lowbit(i))
sum+=c[i];
return sum;
}
}myBIT[maxN];
int main()
{
memset(myBIT,0,sizeof(myBIT));
int order;
while(scanf("%d",&order)==1){
if(order==0){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
myBIT[i].n=n;
continue;
}
if(order==3)
break;
if(order==1){
int x,y,a;
scanf("%d%d%d",&x,&y,&a);
++x,++y;
myBIT[x].modify(y,a);
}
if(order==2){
int l,b,r,t;
scanf("%d%d%d%d",&l,&b,&r,&t);
++l,++b,++r,++t;
int sum=0;
for(int i=l;i<=r;++i)
sum+=myBIT[i].q(t)-myBIT[i].q(b-1);
printf("%d\n",sum);
continue;
}
}
return 0;
}
二维正解:
//poj 1195
//@discuss
#include<stdio.h>
int d[1025][1025];
int n;
int lowbit(int i)
{
return i&(i*(-1));
}
void add(int i,int j,int w)
{
int mj=j;
while(i<=n)
{
for(j=mj;j<=n;j+=lowbit(j))
{
d[i][j]+=w;
// j+=lowbit(j);
}
i+=lowbit(i);
}
}
int sum(int i,int j)
{
int mj=j;
int s=0;
while(i>0)
{
for(j=mj;j>0;j-=lowbit(j))
s+=d[i][j];
i-=lowbit(i);
}
return s;
}
int main (void)
{
int m;
int ins;
int a,b,c;
int r;
scanf("%d %d",&m,&n);
while(scanf("%d",&ins),ins!=3)
{
if(ins==1)
{
scanf("%d %d %d",&a,&b,&c);
add(a+1,b+1,c);
}
else if(ins==2)
{
scanf("%d %d %d %d",&a,&b,&c,&r);
printf("%d\n",sum(c+1,r+1)+sum(a,b)-sum(c+1,b)-sum(a,r+1));
}
}
return 0;
}