题目大意:原题链接
题意很简单,就不赘诉了。
解题思路:
使用二维树状数组,很裸的题。
二维的写起来也很方便,两重循环。
Add(int x,int y,int val)表示(x,y)-(n,n)矩形区域被修改val次(在传入参数时val=1)
如果是要修改(x1,y1)-(x2,y2)的矩形区域。
那么可以在(x1,y1)处加1,在(x2+1,y1)处加1,在(x1,y2+1)处加1,在(x2+1,y2+1)处加1,那么总共:
(x1,y1)-(x2,y2)矩形区域被修改1次,(x2+1,y1)-(n,n)矩形区域被修改2次;
(x1,y2+1)-(n,n)矩形区域被修改2次,(x2+1,y2+1)-(n,n)矩形区域被修改4次;
画个坐标图就知道了。而修改偶数次则回到初始状态,即为0;奇数次则变换一次,即为1。
Sum(int x,int y)表示由于(1,1)-(x,y)矩形区域内的点的改变导致点(x,y)被改变的次数求和,即:
点(x,y)被改变的总次数,而查询单点就是求和,再判断奇偶即可。
注意:真没想到cin,cout差别这么大,该题如果用cin,cout输入输出的话会超时。
之前关于这几个函数Add(x1,y1,1);Add(x2+1,y1,1);Add(x1,y2+1,1);Add(x2+1,y2+1,1);
中的坐标加1始终不理解,总感觉会多修改一些地方,现在一看一目了然(后来才知道是题意理解错了)。
C操作意思是要使得矩形区域(1,1)-(3,3)的查询结果为1就行,而不是使得m[i][j]非得变成1
图一和图三分别是坐标加1和不加1的查询结果;
图二和图五分别对应着图一和图四的m[i][j]的变化过程;
图三和图六分别对应着图一和图四的Sum(i,j)的变化过程
很明显从图二可以看出,有些地方并没有真正的变成1,而查询结果却为1;
不加1时修改的范围查询结果只在矩形区域(1,1)-(2,2),而加上1时则符合要求
图一 图二 图三 图四 图五 图六
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int n,T,m[1010][1010]; int lowbit(int x) { return x&(-x); } int Sum(int x,int y) { int res=0; for(int i=x;i>0;i-=lowbit(i)) for(int j=y;j>0;j-=lowbit(j)) res+=m[i][j]; return res; } void Add(int x,int y,int val) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) m[i][j]+=val; } int main() { scanf("%d",&T); while(T--){ int q; scanf("%d%d",&n,&q); memset(m,0,sizeof(m)); char op; int x,y,x1,y1,x2,y2; while(q--){ getchar(); scanf("%c",&op); if(op=='C'){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); Add(x1,y1,1); Add(x2+1,y1,1); Add(x1,y2+1,1); Add(x2+1,y2+1,1); } else{ scanf("%d%d",&x,&y); if(Sum(x,y)%2==0) printf("0 "); else printf("1 "); } } if(T>0) printf(" "); } }