看过这题之后,首先想到的是二维线段树,但是后来做的时候发现不太好搞,因为x和y会相互影响的。
搜了下解题报告,说是用二维树状数组,然后我就自己开始搞。
写过之后虽然AC了,但是跑了1000ms+,感觉太慢了,就搜了下别人的代码,发现我们所理解的二维树状数组有些差别。
我是把每一列当成一个一维的树状数组,等于是n多的一维树状数组,然后这样来看成二维的。
而别人的直接就是用二维来进行查询更新的。
直接看代码吧:
“伪二维树状数组”:
View Code
1 # include<stdio.h> 2 # include<string.h> 3 # define N 1005 4 int sum[N][N],count[N][N]; 5 int Max(int a,int b) 6 { 7 return a>b?a:b; 8 } 9 void insert(int i,int j,int num) 10 { 11 int t1; 12 for(t1=j;t1<=1001;t1+=t1&(-t1)) 13 sum[i][t1]+=num; 14 } 15 int query(int i,int j) 16 { 17 int num=0; 18 while(j>=1) 19 { 20 num+=sum[i][j]; 21 j-=j&(-j); 22 } 23 return num; 24 } 25 int main() 26 { 27 int i,j,ncase,t,n; 28 int x1,y1,x2,y2,num; 29 int MAXx,MAXy,MINx,MINy,ans1,ans2,SS; 30 char word[10]; 31 scanf("%d",&ncase); 32 for(t=1;t<=ncase;t++) 33 { 34 scanf("%d",&n); 35 memset(sum,0,sizeof(sum)); 36 for(i=1;i<=1001;i++) 37 for(j=1;j<=1001;j++) 38 { 39 count[i][j]=1; 40 insert(i,j,1); 41 } 42 printf("Case %d:\n",t); 43 while(n--) 44 { 45 scanf("%s",word); 46 if(word[0]=='A') 47 { 48 scanf("%d%d%d",&x1,&y1,&num); 49 x1++; 50 y1++; 51 count[x1][y1]+=num; 52 insert(x1,y1,num); 53 } 54 else if(word[0]=='D') 55 { 56 scanf("%d%d%d",&x1,&y1,&num); 57 x1++; 58 y1++; 59 if(count[x1][y1]<num) 60 { 61 num=count[x1][y1]; 62 count[x1][y1]=0; 63 } 64 else count[x1][y1]-=num; 65 insert(x1,y1,-num); 66 } 67 else if(word[0]=='M') 68 { 69 scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&num); 70 x1++; 71 y1++; 72 x2++; 73 y2++; 74 if(count[x1][y1]<num) 75 { 76 num=count[x1][y1]; 77 count[x1][y1]=0; 78 } 79 else count[x1][y1]-=num; 80 count[x2][y2]+=num; 81 insert(x1,y1,-num); 82 insert(x2,y2,num); 83 } 84 else 85 { 86 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 87 x1++; 88 y1++; 89 x2++; 90 y2++; 91 MAXx=Max(x1,x2); 92 MINx=x1+x2-MAXx; 93 MAXy=Max(y1,y2); 94 MINy=y1+y2-MAXy; 95 SS=0; 96 for(i=MINx;i<=MAXx;i++) 97 { 98 ans1=query(i,MAXy); 99 ans2=query(i,MINy-1); 100 SS+=ans1-ans2; 101 } 102 printf("%d\n",SS); 103 } 104 } 105 } 106 return 0; 107 }
二维树状数组:
View Code
View Code 1 # include<stdio.h> 2 # include<string.h> 3 # define N 1005 4 int sum[N][N],count[N][N]; 5 int Max(int a,int b) 6 { 7 return a>b?a:b; 8 } 9 void insert(int i,int j,int num) 10 { 11 int t1,t2; 12 for(t1=i;t1<=1001;t1+=t1&(-t1)) 13 for(t2=j;t2<=1001;t2+=t2&(-t2)) 14 sum[t1][t2]+=num; 15 } 16 int query(int i,int j) 17 { 18 int num=0,t1,t2; 19 for(t1=i;t1>0;t1-=t1&(-t1)) 20 for(t2=j;t2>0;t2-=t2&(-t2)) 21 num+=sum[t1][t2]; 22 return num; 23 } 24 int main() 25 { 26 int i,j,ncase,t,n; 27 int x1,y1,x2,y2,num; 28 int MAXx,MAXy,MINx,MINy,ans1,ans2,SS; 29 char word[10]; 30 scanf("%d",&ncase); 31 for(t=1;t<=ncase;t++) 32 { 33 scanf("%d",&n); 34 memset(sum,0,sizeof(sum)); 35 for(j=1;j<=1001;j++) 36 for(i=1;i<=1001;i++) 37 { 38 count[i][j]=1; 39 sum[i][j]=(i&(-i)) * (j&(-j)); 40 } 41 printf("Case %d:\n",t); 42 while(n--) 43 { 44 scanf("%s",word); 45 if(word[0]=='A') 46 { 47 scanf("%d%d%d",&x1,&y1,&num); 48 x1++; 49 y1++; 50 count[x1][y1]+=num; 51 insert(x1,y1,num); 52 } 53 else if(word[0]=='D') 54 { 55 scanf("%d%d%d",&x1,&y1,&num); 56 x1++; 57 y1++; 58 if(count[x1][y1]<num) 59 { 60 num=count[x1][y1]; 61 count[x1][y1]=0; 62 } 63 else count[x1][y1]-=num; 64 insert(x1,y1,-num); 65 } 66 else if(word[0]=='M') 67 { 68 scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&num); 69 x1++; 70 y1++; 71 x2++; 72 y2++; 73 if(count[x1][y1]<num) 74 { 75 num=count[x1][y1]; 76 count[x1][y1]=0; 77 } 78 else count[x1][y1]-=num; 79 count[x2][y2]+=num; 80 insert(x1,y1,-num); 81 insert(x2,y2,num); 82 } 83 else 84 { 85 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 86 x1++; 87 y1++; 88 x2++; 89 y2++; 90 MAXx=Max(x1,x2); 91 MINx=x1+x2-MAXx; 92 MAXy=Max(y1,y2); 93 MINy=y1+y2-MAXy; 94 SS=0; 95 SS=query(MAXx,MAXy)-query(MAXx,MINy-1)-query(MINx-1,MAXy)+query(MINx-1,MINy-1); 96 printf("%d\n",SS); 97 } 98 } 99 } 100 return 0; 101 }