看过这题之后,首先想到的是二维线段树,但是后来做的时候发现不太好搞,因为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 }

 

 

posted on 2012-04-11 11:52  奋斗青春  阅读(571)  评论(0编辑  收藏  举报