POJ 2155 Matrix (二维树状数组,区间更新,点查找)
题目链接:POJ 2155 Matrix
楼教主出的题。
【题目大意】
给你你 N x N的矩形区域, 开始时每个点的值都为0
有两种操作
C x1 y1 x2 y2 将区域 x1 到 x2 y1 到 y2 围成的矩形区域的值翻转 (1变0 ,0变1);
Q x1,y1,输出 (x1,y1)的值;
典型的区间更新,点查找的题目
相应的一维树状数组题目HDU 1556 Color the ball
在更新的时候同样是先把大区间更新,再把多更新的区间还原。
因为所有节点的值都是0,1 所以我们更新时只用++ ,最后 取余2 就可以了。
和一维树状数组点查询 同样的原理, 统计时向”左“统计翻转次数。
【源代码】
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n,q; const int maxn = 1010; int s[maxn][maxn]; int map[maxn][maxn]; int lowbit(int x){ return x&(-x); } void update(int x,int y){ for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)){ s[i][j]++; } } int query(int x,int y){ int ans=0; for(int i=x;i>0;i-=lowbit(i)) { for(int j=y;j>0;j-=lowbit(j)){ ans+=s[i][j]; } } return ans%2; //取模 } int main(){ int T; scanf("%d",&T); for(int i=1;i<=T;i++){ if(i!=1) puts(""); scanf("%d%d",&n,&q); memset(s,0,sizeof(s)); //不要忘记初始化 char cmd; int x1,y1,x2,y2; while(q--){ scanf(" %c",&cmd); if(cmd=='C'){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); update(x1,y1); //更新大区间 update(x2+1,y1); //抵消掉多余的更新 update(x1,y2+1); //抵消掉多余的更新 update(x2+1,y2+1); //抵消掉多余的更新 } else{ scanf("%d%d",&x1,&y1); printf("%d\n",query(x1,y1)); //直接输出向左上方查询的值 } } } return 0; }