题解报告——矩阵操作
矩阵操作(matrix)
时间限制: 1000 ms 内存限制: 131072 KB
【题目描述】
给定一个N*N的矩阵A,其中每个元素不是0就是1。A[i,j]表示在第i行第j列的数。刚开始,A[i,j] = 0(1 ≤ i, j ≤ N)。
我们可以按照如下的方式改变矩阵。给定一个左上角在(x1,y1),右下角在(x2,y2)的矩形,我们通过使用“not”操作(如果当前这个元素是0,那么变成1,否则变成0)改变这个矩形内的所有元素的值。为了维护矩阵的信息,你需要写个程序来接收并且执行这些操作。
C x1 y1 x2 y2 (1 ≤ x1 ≤ x2 ≤ N, 1 ≤ y1 ≤ y2 ≤ N),代表改变左上角为(x1,y1),右下角为(x2,y2)的矩形区域的值。
Q x y(1 ≤ x, y ≤ n),代表询问A[x,y]的值。
【输入】
第一行包含两个整数N和T(2 ≤ N ≤ 1000,1 ≤ T ≤ 50000),分别代表矩阵的尺寸和操作数。接下来T行每行包含一个指令,以“C x1 y1 x2 y2”或者“Q x y”的形式给出,具体描述如上。
【输出】
对于每个询问操作,输出一行一个整数,代表对应格子的值。
【输入样例】
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
【输出样例】
1 0 0 1
【提示】
有20%的数据保证n ≤ 100且T ≤ 100。
【思路分析】
首先看着道题,一定觉得是要用线性的算法,既然是又有修改又有查询,那么一定可以联想到线段树,但我们清晰地看到,这是一个矩阵,所以是个二维的操作,这就意味着写线段树的话我们就要写二维的线段树,而身为蒟蒻的我,对于二维的线段树根本就没有能力写出来,所以我们需要一个可以轻松从一维跨越的二维的数据结构,那么我们的树状数组就华丽登场了,学习过树状数组的大佬们一定知道,树状数组虽然能力不如线段树,但写起来方便快捷。特别是在多维度的时候更是如鱼得水,只需要在一维的基础上加一个for循环了,是不是贼水,再开个二维数组就好。
偶不再补充一下,我们树状数组只需要记录这个区间修改的次数,只要奇数次就是被修改成了1,不然就还是0.
话不多说马上代码!!!
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int sum[1005][1005]; 5 int n,T; 6 int lowbit(int x) 7 { 8 return ((x)&(-x)); 9 } 10 void change(int x1,int y1) 11 { 12 for(int i=x1;i<=n;i+=lowbit(i)) 13 { 14 for(int j=y1;j<=n;j+=lowbit(j)) 15 { 16 sum[i][j]+=1; 17 } 18 } 19 } 20 int query(int x,int y) 21 { 22 int ans=0; 23 for(int i=x;i>0;i-=lowbit(i)) 24 { 25 for(int j=y;j>0;j-=lowbit(j)) 26 { 27 ans+=sum[i][j]; 28 } 29 } 30 return ans; 31 } 32 int main() 33 { 34 cin>>n>>T; 35 while(T--) 36 { 37 char ord; 38 cin>>ord; 39 if(ord=='C') 40 { 41 42 int x1,x2,y1,y2; 43 cin>>x1>>y1>>x2>>y2; 44 change(x1,y1); 45 change(x1,y2+1); 46 change(x2+1,y1); 47 change(x2+1,y2+1); 48 } 49 else 50 { 51 int x,y; 52 cin>>x>>y; 53 int res=query(x,y); 54 printf("%d\n",(res&1)); 55 } 56 } 57 return 0; 58 }