hoj 1640 Mobile phones //poj 1195 Mobile phones 二维树状数组
/*
(x1,y2) ____________ (x2,y2)
| |
| |
| |
|____________|
(x1,y1) (x2,y1)
在上面的矩形中,本题用树状数组来计算的,所以sum(x2,y2)计算的是它的左下方所有的
手机用户数,但是它多算了sum(x2,y1)以下的以及sum(x1,y2)以下的,若减掉即
ans = sum(x2,y2) - sum(x2,y1) -sum(x1,y2)的话,又减多了sum(x1,y1)部分,那只好加
上这一部分了。
另外,在update(),sum()时,无非算多了一维,很容易理解的,具体看代码,新学到了
i -= lowbit(i) == i = i&(i-1)
i += lowbit(i) == i = (i|(i-1))+1
输入的数据大时速度快很多,比如这题未改前我的代码在hoj上要1.39s,改完后要1.24s
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int X = 1026;
int c[X][X],x,y,n,a,q,row,col;
/*int lowbit(int xx)
{
return xx & -xx;
}*/
int sum(int i,int j)
{
int temp,ans = 0;
while(i>0)
{
temp = j;
while(temp>0)
{
ans += c[i][temp];
//temp -= lowbit(temp);
temp = temp&(temp-1);
}
//i -= lowbit(i);
i = i&(i-1);
}
return ans;
}
void update(int i,int j,int num)
{
int temp;
while(i<=row)
{
temp = j;
while(temp<=col)
{
c[i][temp] += num;
//temp += lowbit(temp);
temp = (temp|(temp-1))+1;
}
//i += lowbit(i);
i = (i|(i-1))+1;
}
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
int x1,x2,y1,y2;
while(scanf("%d",&q)!=EOF) //多case输入
{
if(!q) //指令为0时,重新载入矩形大小,数组c[][]清零
{
scanf("%d",&n);
row = col = n;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
c[i][j] = 0;
}
else if(q==1) //指令为1时,在点(x,y)加上新的数,即update(x,y,num)
{
scanf("%d%d%d",&x,&y,&a);
x++; //给x,y增加一,以免为0时出现死循环
y++;
update(x,y,a);
}
else if(q==2) //指令为2时,计算并输出矩形(x1,y1) (x2,y2)上所有的手机数量(大概意思)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x2++;
y2++;
printf("%d\n",sum(x2,y2)+sum(x1,y1)-sum(x1,y2)-sum(x2,y1));
}
}
return 0;
}