POJ 2155 Matrix(二维BIT维护差分数组)

思路:

1.这道题的要求是让我们在二维的情况下进行区间修改、单点查询;
2.我们首先转变一下思维,将取反变成+1,如果该点是奇数,则说明该点值为1,否则为0
3.我们考虑一下在一维的情况下如何进行区间取反,单点查询;这里我们需要有差分的思想,我们设差分数组为d[],原数组为a[],我们需要做的就是对于每个i,有d[1]+d[2]+...+d[i]=a[i],即原数组a[i]d[i]的前缀和数组;这样做有什么好处呢?我们如果想让原数组从ij每个值都加上k,我们只需要对d[i]+=k且对d[j+1]-=k就好了,大大降低了复杂度;而如果想查询原数组i位置的值,我们只需要对差分数组前i项求和就好了;用BIT来维护这个差分数组,我们很容易可以做到这两个功能;
4.至于二维的情况,和一维情况很类似,对二维BIT(i,j)位置求和,其实就是求所有(x,y)(x<=i&y<=j)位置的和;我们此时进行(x1,y1,x2,y2)区间修改时,需要将(x1,y1)位置加上1,那么接下来是不是对(x2+1,y2+1)位置再加一次1就好了?(注意这里加一次1代表取反一次,我们我们之后采用模2运算),当然不是,我们设区域A是自己要修改的区域:
在这里插入图片描述
我们如果直接对(x2+1,y2+1)加一,那只是对D区域取反了,那C和B被(x1,y1)加一操作所造成的影响并没有被抵消,此时我们分别对(x1,y1) (x1,y2+1)(x2+1,y1)(x2+1,y2+1)都加一,那么A区域都被取反了,BCD区域都被取反了两次(互相抵消了),我们就成功的只对A区域进行了操作;

代码:

#include<iostream>
using namespace std;
const int maxn=1005;
int bit[maxn][maxn],n,t;
#define lowbit(x) (x&-x)
int bit_sum(int x,int y){
	int s=0;
	while(x>0){
		int t=y;
		while(t>0) s+=bit[x][t],t-=lowbit(t);
		x-=lowbit(x);
	}
	return s;
}
void bit_add(int x,int y){
	while(x<=n){
		int t=y;
		while(t<=n) bit[x][t]++,t+=lowbit(t);
		x+=lowbit(x);
	}
}
void change(int& x1,int& y1,int& x2,int& y2){
	bit_add(x1,y1);
	bit_add(x2+1,y2+1);
	bit_add(x2+1,y1);
	bit_add(x1,y2+1);
}
void End(){
	for(int i=0;i<=n;i++){
		for(int j=i;j<=n;j++) bit[i][j]=bit[j][i]=0;
	}
	puts("");
}
void solve(){
	char c;
	while(c=getchar(),c!='C'&&c!='Q');
	if(c=='C'){
		int x1,y1,x2,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		change(x1,y1,x2,y2);
	}else{
		int x,y;
		scanf("%d%d",&x,&y);
		cout<<(bit_sum(x,y)&1)<<'\n';  
	}
}
int main(){
//	freopen("Arutoria.txt","r",stdin);
	int X; scanf("%d",&X);
	while(X--){
		scanf("%d%d",&n,&t);
		while(t--) solve();
		End();
	}
	return 0;
}
posted @ 2019-12-04 10:34  YuhanのBlog  阅读(151)  评论(0编辑  收藏  举报