本题也属于比较简单的二维树状数组问题。
思路很简单:单点向上记录,向下求和,不过一直AC不了,总结一下每次出现错误的原因:
1、一开始mle。。。后来查了一下,是因为数组开得太大,看来数组还是要看情况来开,根据情况,适合就好。
2、然后就是各种WA。。。对比AC代码后发现,是因为一下两个原因:a、对于单点书本的判断的表达式书写出错。(应该和区域的计算表达式差不多) b、除了add外其他的update函数在更新时坐标都不需要+1,因为add的时候,已经从(1,1)开始取,所以后面的其他操作也就不用+1。
3、当我以为这些问题都解决,可以AC时,OJ抛出了了个TLE。。。检查了好多遍感觉都不会T啊,可是事实就是如此残忍。。。在我把主算法一个个换走后发现,原来是if-else太多引起的问题。原来if-else 也会增加复杂度。以后应该要对题目给出的数据敏感一点,如<=10,就是为了让我用for循环进行初始化c数组为1。,
先附上AC代码(此为转载的代码,因为自己后来修改的版本已经几乎接近这个了,所以直接上这个):
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int size = 1010;
int a[size+1][size+1];
int lowbit(int i)
{
return i & (-i);
}
void add(int x, int y, int num)
{
for(int i = x; i <= size; i += lowbit(i))
for(int j = y; j <= size; j += lowbit(j))
a[i][j] += num;
}
int getSum(int x, int y)
{
int tot = 0;
for(int i = x; i > 0; i -= lowbit(i))
for(int j = y; j > 0; j -= lowbit(j))
tot += a[i][j];
return tot;
}
void init()
{
memset(a, 0, sizeof(a));
for(int i = 1; i < size; ++i)
for(int j = 1; j < size; ++j)
add(i, j, 1);
}
int main()
{
int T, n, x1, x2, y1, y2, n1;
char cmd[3];
scanf("%d", &T);
for(int cnt = 1; cnt <= T; ++cnt)
{
init();
scanf("%d", &n);
printf("Case %d:\n", cnt);
while(n--)
{
scanf("%s", cmd);
if(cmd[0] == 'A')
{
scanf("%d%d%d", &x1, &y1, &n1);
add(x1+1, y1+1, n1);
}
else if(cmd[0] == 'S')
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
++x1;
++x2;
++y1;
++y2;
if(x1 > x2)
swap(x1, x2);
if(y1 > y2)
swap(y1, y2);
int temp;
temp=getSum(x2,y2)-getSum(x1-1,y2)-getSum(x2,y1-1)+getSum(x1-1,y1-1);
printf("%d\n",temp);
}
else if(cmd[0] == 'D')
{
scanf("%d%d%d",&x1,&y1,&n1);
++x1;
++y1;
int temp;
temp=getSum(x1,y1)-getSum(x1-1,y1)-getSum(x1,y1-1)+getSum(x1-1,y1-1);
if(n1 > temp)
n1 = temp;
add(x1, y1, -n1);
}
else if(cmd[0] == 'M')
{
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &n1);
++x1;
++x2;
++y1;
++y2;
int temp;
temp=getSum(x1,y1)-getSum(x1-1,y1)-getSum(x1,y1-1)+getSum(x1-1,y1-1);
if(n1 > temp)
n1 = temp;
add(x1, y1, -n1);
add(x2, y2, n1);
}
}
}
return 0;
}
TLE:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1011;
int c[maxn+1][maxn+1],n,casenum,cases=0,queries;
char str[10];
int lowbit(int x)
{
return x&(-x);
}
void update(int i,int j,int val)
{
for(int x=i;x<maxn;x+=lowbit(x))
for(int y=j;y<maxn;y+=lowbit(y))
{
c[x][y]+=val;
}
}
int getsum(int i,int j)
{
int result=0;
for(int x=i;x>0;x-=lowbit(x))
{
for(int y=j;y>0;y-=lowbit(y)){
result+=c[x][y];
}
}
return result;
}
void init()
{
memset(c,0,sizeof(c));
for(int i=1;i<maxn;i++)
for(int j=1;j<maxn;j++)
update(i,j,1);
}
int main()
{
scanf("%d",&casenum);
while(casenum--)
{
cases++;
printf("Case %d:\n",cases);
init();
scanf("%d%*c",&queries);
for(int i=1;i<=queries;i++)
{
scanf("%s",str);
if(str[0]=='S')
{
int x1,x2,y1,y2,n1,n2,m1,m2,sum;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
n1=max(x1,x2);
n2=min(x1,x2);
m1=max(y1,y2);
m2=min(y1,y2);
sum=getsum(n1+1,m1+1)-getsum(n2,m1+1)-getsum(n1+1,m2)+getsum(n2,m2);
printf("%d\n",sum);
}
if(str[0]=='A')
{
int xx,yy,nn;
scanf("%d%d%d",&xx,&yy,&nn);
update(xx+1,yy+1,nn);
}
if(str[0]=='D')
{
int xxx,yyy,nnn,t;
scanf("%d%d%d",&xxx,&yyy,&nnn);
t=getsum(xxx,yyy)-getsum(xxx,yyy+1)-getsum(xxx+1,yyy)+getsum(xxx,yyy);
if(t<=nnn)
update(xxx,yyy,-t);
else
update(xxx,yyy,-nnn);
}
if(str[0]=='M')
{
int xx1,xx2,yy1,yy2,tt,nnnn;
scanf("%d%d%d%d%d",&xx1,&yy1,&xx2,&yy2,&nnnn);
tt=getsum(xx1+1,yy1+1)-getsum(xx1,yy1+1)-getsum(xx1+1,yy1)+getsum(xx1,yy1);
if(nnnn>=tt)
{
update(xx1,yy1,-tt);
update(xx2,yy2,tt);
}
else
{
update(xx1,yy1,-nnnn);
update(xx2,yy2,nnnn);
}
}
}
}
return 0;
}