这道题是一个二维树状数组,思路十分神奇,其实还是挺水的
题目描述
给定一个N∗NN∗N的矩阵AA,其中矩阵中的元素只有0或者1,其中A[i,j]A[i,j]表示矩阵的第i行和第j列(1≤i,j≤N)(1≤i,j≤N),初始矩阵元素都是0。在矩阵上进行TT次操作,操作有以下两种:
(1)格式为C x1 y1 x2 y2(1≤x1≤x2≤n,1≤y1≤y2≤n)C x1 y1 x2 y2(1≤x1≤x2≤n,1≤y1≤y2≤n) ,其中CC为字符“C”,表示把以(x1,y1)(x1,y1)为左上角,(x2,y2)(x2,y2)为右下角的这个矩形内的每一个数字同1异或
(2)格式为Q x y(1≤x,y≤n)Q x y(1≤x,y≤n),其中QQ为字符“Q”, 表示询问A[x,y]A[x,y]的值。
输入格式
第一行输入XX,表示X组测试数据
接下来每一组测试数据第一行包含两个整数NN和TT,其中NN表示矩阵的大小,TT表示对矩阵操作次数。
接下来TT行形式如 "Q x y" or "C x1 y1 x2 y2"操作,见题目中描述
输出格式
对于每个Q x yQ x y的操作输出答案A[x,y]A[x,y]。
样例一
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
output
1 0 0 1
限制与约定
对于30%的数据N≤100,T≤3000N≤100,T≤3000
对于50%的数据N≤500,T≤20000N≤500,T≤20000
对于100%的数据N≤1000,T≤50000,X≤10N≤1000,T≤50000,X≤10
时间限制:1s1s
空间限制:256MB
首先二维树状数组的标准写法
1 #define lowbit(a) (a)&(-a) 2 void change(int px,int py,int val) 3 { 4 for(int i=px;i<=n;i+=lowbit(i)) 5 for(int j=py;j<=n;j+=lowbit(j)) 6 tree[i][j]=(tree[i][j]+val)%2; 7 } 8 int ask(int px,int py) 9 { 10 int ans=0; 11 for(int i=px;i;i-=lowbit(i)) 12 for(int j=py;j;j-=lowbit(j)) 13 ans=(ans+tree[i][j])%2; 14 return ans; 15 }
就是一维树状数组加了一层循环,很好理解的233
这道题需要打个差分,差分个人理解就是把正常一个数组i与i-1做差,得到的一个差分数组,然后查询时累加前缀和,这么做有很多方便的地方,比如洛谷的树状数组2
来介绍一下差分
设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5}
也就是说b[i]=a[i]-a[i-1];(a[0]=0;),那么a[i]=b[1]+....+b[i];(这个很好证的)。
假如区间[2,4]都加上2的话
a数组变为a[]={1,8,10,7,10},b数组变为b={1,7,2,-3,3};
发现了没有,b数组只有b[2]和b[5]变了,因为区间[2,4]是同时加上2的,所以在区间内b[i]-b[i-1]是不变的.
所以对区间[x,y]进行修改,只用修改b[x]与b[y+1]:
b[x]=b[x]+k;b[y+1]=b[y+1]-k;
以上就是差分的应用,对于区间修改时应该想到差分,
比如这道题,就是矩阵的子矩阵修改,这种方法就非常nice
看下面这张图,修改绿色部分,只需把红色的都+1%2,再累加前缀和能满足(图片出处在水印233)
其实差分区间修改都可以理解为,比如修改(x,y)全部加2,只要把差分数组中x位置,然后再把y+1减2,就能完美解决,配上树状数组,这样修改和查询就就是O(log(n)),时间复杂度满足
注意要清数组清数组清数组清数组清数组,没清数组只A了一个点QAQ
最后放代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define lowbit(a) (a)&(-a) 5 int t,n,k,x,y,z,w; 6 int tree[1111][1111]; 7 char opt[5]; 8 void change(int px,int py,int val) 9 { 10 for(int i=px;i<=n;i+=lowbit(i)) 11 for(int j=py;j<=n;j+=lowbit(j)) 12 tree[i][j]=(tree[i][j]+val)%2; 13 } 14 int ask(int px,int py) 15 { 16 int ans=0; 17 for(int i=px;i;i-=lowbit(i)) 18 for(int j=py;j;j-=lowbit(j)) 19 ans=(ans+tree[i][j])%2; 20 return ans; 21 } 22 int main() 23 { 24 scanf("%d",&t); 25 while(t--) 26 { 27 memset(tree,0,sizeof(tree)); 28 scanf("%d%d",&n,&k); 29 for(int i=1;i<=k;i++) 30 { 31 scanf("%s",opt); 32 if(opt[0]==‘C‘) 33 { 34 scanf("%d%d%d%d",&x,&y,&z,&w); 35 change(x,y,1),change(z+1,w+1,1),change(x,w+1,1),change(z+1,y,1); 36 }else if(opt[0]==‘Q‘) 37 { 38 scanf("%d%d",&x,&y); 39 printf("%d\n",ask(x,y)); 40 } 41 } 42 } 43 return 0; 44 }
By 浅夜_MISAKI
原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10052168.html