POJ 2155 Matrix 二维树状数组

 1 #include<iostream>
 2 #include<math.h>
 3 #include<string.h>
 4 #include<queue>
 5 #include<algorithm>
 6 #include<cstdio>
 7 #define rep(i,a,n) for(i=a;i<=n;i++)
 8 #define per(i,a,n) for(i=n;i>=a;i--)
 9 #define scd1(a) scanf("%d",&a)
10 #define scd2(a,b) scanf("%d%d",&a,&b)
11 #define ll long long
12 #define mem(a,b) memset(a,b,sizeof a);
13 using namespace std;
14 
15 const int maxn=1000;
16 int T,cnt=0,N,M;
17 int mt[maxn+5][maxn+5];
18 char ist;
19 
20 int lowbit(int num){
21     return num&(-num);
22 }
23 
24 void add(int x, int y, int d){
25     while(x<=N){
26         int j=y;
27         while(j<=N){
28             mt[x][j]+=d;j+=lowbit(j);
29         }x+=lowbit(x);
30     }
31 }
32 
33 int sum(int x, int y){
34     int ret=0;
35     while(x>0){
36         int j=y;
37         while(j>0){
38             ret+=mt[x][j];j-=lowbit(j);
39         }
40         x-=lowbit(x);
41     }
42     return ret;
43 }
44 
45 int main(){
46     scanf("%d",&T);
47     while(T--){
48         mem(mt,0);
49         scanf("%d%d ",&N,&M);
50         int i;
51         rep(i,1,M){
52             scanf("%c",&ist);
53             if(ist=='C'){
54                 int x1,x2,y1,y2;
55                 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
56                 add(x1,y1,1);
57                 add(x1,y2+1,-1);
58                 add(x2+1,y1,-1);
59                 add(x2+1,y2+1,1);
60             }
61             else if(ist=='Q'){
62                 int x,y;
63                 scd2(x,y);
64                 int ans=sum(x,y);
65                 printf("%d\n",ans%2);
66             }
67             getchar();
68         }
69         if(T)printf("\n");
70     }
71 }
View Code

题意描述: 给出一个矩阵每个点的初值, 每次操作可以对一个子矩阵内的值进行加减, 每次质询要求给出矩阵中某个点的值.

就是一个裸的二维树状数组. 见代码. 它的对偶题是POJ1195 Mobile Phones, 那个题是每次改一个点的值, 每次质询要求给出一个子矩阵内的数值和. 代码只要改一改就能过. 题解链接: http://www.cnblogs.com/LiXinze/p/7353451.html

当然这种题也可以用线段树来做, 只不过稍微会麻烦一点.

posted @ 2017-08-13 14:33  Li_Xinze  阅读(159)  评论(0编辑  收藏  举报