poj 2155 Matrix

/*

题意: 给定一个0-1矩阵,在线对在范围[x1,y1]-[x2,y2]之内的元素置反,在线求[x,y]元素值

思路: 表面上看,这题的要求似乎和树状数组的使用方法恰好相反,改变的是一个区间,查询的反而是一个点。
实际上可以通过一个转化巧妙的解决。
首先对于每个数A定义集合up(A)表示{A, A+lowbit(A), A+lowbit(A)+lowbit(A+lowbit(A))...}
定义集合down(A)表示{A, A-lowbit(A), A-lowbit(A)-lowbit(A-lowbit(A)) ... , 0}。
可以发现对于任何A<B,up(A)和down(B)的交集有且仅有一个数C[]。
于是对于这道题目来说,翻转一个区间[A,B](为了便于讨论先把原问题降为一维的情况),
我们可以把up(A)的所有元素的翻转次数+1,再把up(B+1)的所有元素的翻转次数-1。
而每次查询一个元素d时,只需要统计down(d)的所有元素C[]的翻转次数之和,即为元素d实际被翻转的次数。
由于这道题实际上只需考虑翻转次数的奇偶性,因此无须统计确切的翻转次数。

*/

#include <iostream> //二维树状数组
using namespace std;
int table[1001][1001],n; //树状数组下标范围从[1,1]到[n,n]
int lowbit(int x)
{
return x&(-x);
}
void modify(int x, int y) //求up(x,y)
{
int i=x;
while(i<=n)
{
int j=y;
while(j<=n)
{
table[i][j]++;
j+=lowbit(j);
}
i+=lowbit(i);
}
}
int sum(int x,int y) //求down(x,y)
{
int s=0;
int i=x;
while(i>0)
{
int j=y;
while(j>0)
{
s+=table[i][j];
j-=lowbit(j);
}
i-=lowbit(i);
}
return s;
}
int main()
{
int cases,t;
cin>>cases;
while(cases--)
{
memset(table,0,sizeof(table));
scanf("%d%d",&n,&t);
while(t--)
{
char tag;
cin>>tag;
if(tag=='C')
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
modify(x1,y1);
modify(x1,y2+1);
modify(x2+1,y1);
modify(x2+1,y2+1);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",sum(x,y)%2);
}
}
printf("\n");
}
return 0;
}

posted on 2011-07-20 22:47  sysu_mjc  阅读(157)  评论(0编辑  收藏  举报

导航