Appoint description:
Description
Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N).
We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.
1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].
We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.
1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].
Input
The first line of the input is an integer X (X <= 10) representing the number of test cases. The following X blocks each represents a test case.
The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.
The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.
Output
For each querying output one line, which has an integer representing A[x, y].
There is a blank line between every two continuous test cases.
There is a blank line between every two continuous test cases.
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
如果还不会二位树状数组,这里有一篇博客讲树状数组所有基本应用都讲得很详细很好,可以去学一下:http://blog.csdn.net/qq_34374664/article/details/52787481
题意:每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1.
思路:典型的二位树状数组,用以前的区间更新单点查询比较好理解。。。一开始更新x1,y1,这样x1-n,y1-n都给+1了,所以要将x1, y2+1, 减一,x1+1,y2减一 这样之后x2 y2 就多减了一次1所以要再加一次1、
由于是0-1矩阵,只需用tre[][]记录一个元素被置反的次数即可,当对(x1,y1),(x2,y2)区间置反时,需要改动四个地方就是4个角就可以了。为什么呢?如下图,假设A区未需要置反的区域,因为改动A区的左上角时,由树状数组的性质知:A,B,C,D4个区域都是要被置反的,所以在依次置反BD,CD,D,这样,置反的总过程为ABCD,BD,CD,D,这样我们就会发现结果对2取模时,只有A区被置反,B,C,D三个区都没有变化。明白原理之后就好做了。
A | B |
C | D |
树状数组代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1e3 + 5;
int c[maxn][maxn], t, n, m;
void update(int x, int y, int val)
{
while(x <= n)
{
int y1 = y;
while(y1 <= n)
{
c[x][y1] += val;
y1 += y1 & -y1;
}
x += x & -x;
}
}
int sum(int x, int y)
{
int s = 0;
while(x > 0)
{
int y1 = y;
while(y1 > 0)
{
s += c[x][y1];
y1 -= y1 & -y1;
}
x -= x & -x;
}
return s;
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n, &m);
memset(c, 0, sizeof(c));
char ch;
while(m--)
{
int x1, x2, y1, y2;
scanf(" %c", &ch);
if(ch == 'C')
{
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
update(x1, y1, 1); //按照题解的思路 这里都可以是+1的,因为多翻转一次等于没有翻转
update(x1, y2+1, -1);
update(x2+1, y1, -1);
update(x2+1, y2+1, 1);
}
if(ch == 'Q')
{
scanf("%d%d", &x1, &y1);
printf("%d\n", sum(x1,y1)%2);
}
}
printf("\n");
}
return 0;
}
kuangbin线段树代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MAXN = 1010;
struct Nodey
{
int l,r;
int val;
};
int n;
int locx[MAXN],locy[MAXN];
struct Nodex
{
int l,r;
Nodey sty[MAXN*3];
void build(int i,int _l,int _r)
{
sty[i].l = _l;
sty[i].r = _r;
sty[i].val = 0;
if(_l == _r)
{
locy[_l] = i;
return;
}
int mid = (_l + _r)>>1;
build(i<<1,_l,mid);
build((i<<1)|1,mid+1,_r);
}
void add(int i,int _l,int _r,int val)
{
if(sty[i].l == _l && sty[i].r == _r)
{
sty[i].val += val;
return;
}
int mid = (sty[i].l + sty[i].r)>>1;
if(_r <= mid)add(i<<1,_l,_r,val);
else if(_l > mid)add((i<<1)|1,_l,_r,val);
else
{
add(i<<1,_l,mid,val);
add((i<<1)|1,mid+1,_r,val);
}
}
}stx[MAXN*3];
void build(int i,int l,int r)
{
stx[i].l = l;
stx[i].r = r;
stx[i].build(1,1,n);
if(l == r)
{
locx[l] = i;
return;
}
int mid = (l+r)>>1;
build(i<<1,l,mid);
build((i<<1)|1,mid+1,r);
}
void add(int i,int x1,int x2,int y1,int y2,int val)
{
if(stx[i].l == x1 && stx[i].r == x2)
{
stx[i].add(1,y1,y2,val);
return;
}
int mid = (stx[i].l + stx[i].r)/2;
if(x2 <= mid)add(i<<1,x1,x2,y1,y2,val);
else if(x1 > mid)add((i<<1)|1,x1,x2,y1,y2,val);
else
{
add(i<<1,x1,mid,y1,y2,val);
add((i<<1)|1,mid+1,x2,y1,y2,val);
}
}
int sum(int x,int y)
{
int ret = 0;
for(int i = locx[x];i;i >>= 1)
for(int j = locy[y];j;j >>= 1)
ret += stx[i].sty[j].val;
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int q;
scanf("%d%d",&n,&q);
build(1,1,n);
char op[10];
int x1,x2,y1,y2;
while(q--)
{
scanf("%s",op);
if(op[0] == 'C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add(1,x1,x2,y1,y2,1);
}
else
{
scanf("%d%d",&x1,&y1);
if(sum(x1,y1)%2 == 0)printf("0\n");
else printf("1\n");
}
}
if(T)printf("\n");
}
return 0;
}