hdu 1892
本题是二维的树状数组的基本应用,非常好,要先读懂题意:
有很多方格,每个方格对应的坐标为(I,J),刚开始时每个格子里有1本书,然后让你统计一片区域有多少本书,还可以增加书和减少,移动书。
注意本题的坐标是从0开始的,而树状数组必须从1开始,否则会死循环,所以输入坐标后,都先自动+1了;
二维的模版基本也是不变的! lowbit () update() query()
代码:
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
const int maxn=1008;
int tree[maxn+2][maxn+2];
int lowbit(int t)
{
return t & (-t);
}
void update(int x,int y,int val)
{
for(int i=x;i<maxn;i+=lowbit(i))
for(int j=y;j<maxn;j+=lowbit(j))
tree[i][j]+=val;
}
int query(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+=tree[i][j];
return sum;
}
int main()
{
int t,n,n1,x1,y1,x2,y2,i,j,num;
char s[20];
cin>>t;
num=t;
while(t--)
{
printf("Case %d:\n",num-t);
memset(tree,0,sizeof(tree));
for(int i=1;i<=maxn;i++)
for(int j=1;j<=maxn;j++)
update(i,j,1);
cin>>n;
for(int k=1;k<=n;k++)
{
scanf("%s",s);
if (s[0]=='A') //在i,j 这个位置放书
{
scanf("%d%d%d",&i,&j,&n1);
i++;j++;
update(i,j,n1);
}
if (s[0]=='S')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if (x1>x2) swap(x1,x2);
if (y1>y2) swap(y1,y2);
x1++;y1++;x2++;y2++;
int ans=query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1);
printf("%d\n",ans);
}
if (s[0]=='D')
{
scanf("%d%d%d",&i,&j,&n1);
i++;j++;
int val_1=0;//i,j点的有多少书
val_1=query(i,j)-query(i-1,j)-query(i,j-1)+query(i-1,j-1);
int min_1=min(val_1,n1);
update(i,j,-1*(min_1));
}
if (s[0]=='M')
{
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&n1);
x1++;y1++;x2++;y2++;
int val_0=0;//x1,y1点有多少书
val_0=query(x1,y1)-query(x1-1,y1)-query(x1,y1-1)+query(x1-1,y1-1);
int min_0=min(val_0,n1);
update(x1,y1,-1*min_0);
update(x2,y2,min_0);
}
}
}
// cout << "Hello world!" << endl;
return 0;
}