您的位置:首页 > 其它

POJ 2155 Matrix(树状数组+单点更新)

2015-02-21 17:30 127 查看
好多天没干活了,赶紧更新一篇。

题意:给定一矩阵,初始值均为0。现有两种操作:1.将以(x1, y1)为左上角,(x2, y2)为右下角的矩阵中的所有0变为1,所有1变为0;2.查询位置(x, y)是0还是1。

要点:

1.sum(i)是求第i位的前缀和,add(i)是更新位置i的单点值。

2.翻转两次相当于没有翻转。

假设x为位置i的翻转次数,那么可以将x看做一个集合,x = { x + 2 * k | k =  整数 }【格式不是很标准,意会一下】;

令i的前缀和为位置i的翻转次数的集合中的一个元素。



假设要给绿色部分都反转,那么绿色部分里面的每个点的前缀和都要加一个奇数,比如1;

可给绿色部分的左上角加一,这样绿色部分的每个点求前缀和的时候都会加一了;

但是这样紫色部分和肤色部分还有粉红色部分也加了一;

所以还要加,把三个部分加成偶数;

于是加绿色右上角,绿色左下角,绿色右下角都加1;

这样肤色和粉色部分的前缀和都加了2,紫色部分是加了4,消除了绿色左上角加一的影响。

剩下的就是二维树状数组乱搞了。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
#define MAXN 1005

int s[MAXN][MAXN];
char o[4];
int x1, x2, y1, y2, n, q, ans;

inline int lowbit(int x)
{
return x & (-x);
}

int sum(int i, int j)
{
int ret = 0;
while(i > 0)
{
int tj = j;
while(tj > 0)
{
ret += s[i][tj];
tj -= lowbit(tj);
}
i -= lowbit(i);
}
return ret;
}

void add(int i, int j)
{
while(i <= n)
{
int tj = j;
while(tj <= n)
{
s[i][tj]++;
tj += lowbit(tj);
}
i += lowbit(i);
}
}

int main()
{
//    freopen("B.in", "r", stdin);

int t; scanf("%d", &t);
bool flag = false;
while(t--)
{
if(flag) puts("");
if(!flag) flag = true;

scanf("%d%d", &n, &q);
memset(s, 0, sizeof(s));

while(q--)
{
scanf("%s", o);
if(o[0] == 'C')
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
add(x1, y1);
add(x1, y2 + 1);
add(x2 + 1, y1);
add(x2 + 1, y2 + 1);

}
if(o[0] == 'Q')
{
scanf("%d%d", &x1, &y1);
ans = sum(x1, y1);// - sum(x1, y1 - 1) - sum(x1 - 1, y1) + sum(x1 - 1, y1 - 1);
printf("%d\n", ans & 1);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: