![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
题意描述: 给出一个矩阵每个点的初值, 每次操作可以对一个子矩阵内的值进行加减, 每次质询要求给出矩阵中某个点的值.
就是一个裸的二维树状数组. 见代码. 它的对偶题是POJ1195 Mobile Phones, 那个题是每次改一个点的值, 每次质询要求给出一个子矩阵内的数值和. 代码只要改一改就能过. 题解链接: http://www.cnblogs.com/LiXinze/p/7353451.html
当然这种题也可以用线段树来做, 只不过稍微会麻烦一点.