树状数组之四

#include <iostream>            //POJ 2155 Matrix  树状数组
using namespace std;
int tree[1001][1001],n;
int lowbit(int x) //lowbit函数是计算x表示二进制,从最低位开始向左数,第一个不为0的数字的权值,比如x=6=110,则返回2
{
return x&(-x);
}
void modify(int x, int y) //求up(x,y)
{
int i=x;
while(i<=n)
{
int j=y;
while(j<=n)
{
tree[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>=1)
{
int j=y;
while(j>=1)
{
s
+=tree[i][j];
j
-=lowbit(j);
}
i
-=lowbit(i);
}
return s;
}
int main()
{
int c,t;char tag;
int x,y,x1,y1,x2,y2;
cin
>>c;
while(c--)
{
memset(tree,
0,sizeof(tree));
scanf(
"%d%d",&n,&t);
while(t--)
{
cin
>>tag;
if(tag=='C')
{
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
{
scanf(
"%d%d",&x,&y);
printf(
"%d\n",sum(x,y)%2);
}
}
printf(
"\n");
}
return 0;
}


//树状数组是一个很有用的数据结构,数组内元素的修改和查询区间段元素合是此数据结构的两个基本操作,
//这里用到两个数组a[],C[]。a数组是原数组,仅用于理解,
//编码时不用有a数组,基本内容就是用C[]数组根据公式来对应相关的原数组a[],通过对C[]数组的操作来实现它的两个基本操作
//1。修改a中单个元素2。区间求和,的时间复杂度均为O(logN)

//参照 http://hi.baidu.com/xiaohanhoho/blog/item/2888703c984c64e73c6d973c.html

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

  

posted on 2011-07-17 01:54  sysu_mjc  阅读(139)  评论(0编辑  收藏  举报

导航