对应 POJ 题目:点击打开链接
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 22905 | Accepted: 8492 |
Description
Input
Output
Sample Input
1 2 10 C 2 1 2 2 Q 2 2 C 2 1 2 1 Q 1 1 C 1 1 2 1 C 1 2 1 2 C 1 1 2 2 Q 1 1 C 1 1 2 1 Q 2 1
Sample Output
1 0 0 1
题意:
先输入一个数 X,表示有 X 组数据;然后输入两个数 N,T;N 表示初始值为全 0 的 N*N 矩阵,T 表示有 T 个操作;接下来 T 行操作:(C x1 y1 x2 y2) 表示把以 (x1, y1) 坐标为左上角,(x2, y2) 坐标为右下角的矩阵的属性翻转(如果是 1 的变为 0,是 0 的变为 1);(Q x y) 表示询问 (x y) 坐标的点的属性(是 1 或 0)。
思路:
二维树状数组(基础:点击打开链接 点进去下面有翻译 或 点击打开链接)。
先来看一维的情况:
n张卡片摆成一排,分别为第1张到第n张,开始时它们都是下面朝下的。你有两种操作:
T(i,j):将第i张到第j张卡片进行翻转,包含i和j这两张。(正面变反面,反面变正面)
Q(i):如果第i张卡片正面朝下,返回0;否则返回1.
解决方案:
设数组f初始全为0,当做一次T(i, j)操作后, 将f[i]加1,f[j+1]减1。这样一来,当我们做一次Q(i)时,只需要求f数组的前i项和sum[i] ,然后对2取模即可。当我们做完一次T(i, j)后,f[i]=1,f[j+1]=-1。 这样一来,当k<i时,sum[k]%2=0,表明正面朝下;当i<=k<=j时,sum[k]%2=1,表明正面朝 上(因为这区间的卡片都被翻转了!);当k>j时,sum[k]%2=0,表示卡片正面朝下。 Q(i)返回的正是我们要的判断。
二维的也可以用类似的方法,(注意坐标轴的轴心是在左上角,不是左下角)。把以 (x1, y1) 坐标为左上角,(x2, y2) 坐标为右下角的矩阵的属性取反,就相当于在点 (x1, y1) 加 1,点 (x2 +1, y1) 减 1,点 (x1, y2 +1) 减 1,点 (x2 + 1, y2 + 1) 加 1;而求矩阵中某点的属性就相当于对以 (1, 1) 坐标为左上角,(x, y) 坐标为右下角的矩阵的元素求和然后对 2 取模;在理解了二维树状数组后,这点不难理解。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 1005 #define max_x 1000 #define max_y 1000 int c[N][N]; int lowbit(int x) { return (x & (-x)); } void update(int x, int y, int val) { while(x <= max_x){ int yt = y; while(yt <= max_y){ c[x][yt] += val; yt += lowbit(yt); } x += lowbit(x); } } int query(int x, int y) { int s = 0; while(x > 0){ int yt = y; while(yt > 0){ s += c[x][yt]; yt -= lowbit(yt); } x -= lowbit(x); } return s; } int main() { #if 0 freopen("in.txt","r",stdin); #endif int T; scanf("%d", &T); while(T--){ int n, m; char od[3]; memset(c, 0, sizeof(c)); scanf("%d%d", &n, &m); while(m--){ scanf("%s", od); if(od[0] == 'C'){ int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); update(x1, y1, 1); update(x2 + 1, y1, -1); update(x1, y2 + 1, -1); update(x2 + 1, y2 + 1, 1); } else if(od[0] == 'Q'){ int x, y; scanf("%d%d", &x, &y); printf("%d\n", query(x, y) % 2); } } if(T) printf("\n"); } return 0; }