题目大意

给定初始值为\(0\)的\(n*n\)矩阵

两种操作

  1. 矩形内异或一个值
  2. 求矩阵内异或和

    \(n\le 1000\)

分析

二维线段树标记不下传貌似直接可做

有没有更简便的方法?

考虑异或的特性

我们修改\((u,v)-(x,y)时(u\le x,v\le y)\)

修改\((u,v)\),\((x+1,y+1)\),\((x+1,v)\),\((u,y+1)\)这四个单点的值\(a(x,y)\)

然后考虑我们只询问单点\(val(x,y)\)时

那么我们只需要计算$$\bigotimes_{i=1}x\bigotimes_{j=1}y a(x,y)$$

然后再考虑我们询问矩形\((u,v)-(x,y)\)时

首先差分成四个形如\((1,1)-(X,Y)\)的询问,然后写下式子找规律

\[\begin{aligned}
&\bigotimes_{i=1}^X\bigotimes_{j=1}^Y val(i,j)\\
=&\bigotimes_{i=1}^X\bigotimes_{j=1}^Y \bigotimes_{x=1}^i\bigotimes_{y=1}^j a(x,y)\\
=&\bigotimes_{x=1}^X\bigotimes_{y=1}^Y\left(\bigotimes_{i=1}^{X-x+1}~\bigotimes_{j=1}^{Y-y+1}a(x,y)\right)\\
=&\bigotimes_{x=1}^X\bigotimes_{y=1}^Y [x,X奇偶同][y,Y奇偶同] a(x,y)
\end{aligned}
\]

按(x,y)的奇偶性分成四个树状数组维护

可以发现任意两个树状数组没有公共点

注意我们把val化成了a

这样我们就只需要单点修改四个位置(修改到对应树状数组里)

然后询问的时候到(X,Y)奇偶性对应的树状数组里查询即可

solution

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
using namespace std;
const int M=1e3+7;
typedef long long LL; inline int ri(){
int x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
} inline LL rl(){
LL x=0;bool f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(;isdigit(c);c=getchar()) x=x*10+c-48;
return f?x:-x;
} int n,m; struct Bit{
int c[M][M];
Bit(){memset(c,0,sizeof c);}
inline int lb(int x){return x&-x;}
inline void add(int x,int y,LL d){
int i,j;
if(x==0||y==0) return;
for(i=x;i<=n;i+=lb(i))
for(j=y;j<=n;j+=lb(j)) c[i][j]^=d;
}
inline LL sum(int x,int y){
int i,j; LL res=0;
for(i=x;i>0;i-=lb(i))
for(j=y;j>0;j-=lb(j)) res^=c[i][j];
return res;
}
}C[2][2]; inline int id(int x){return (x+1)>>1;} LL get(int x,int y){
return C[x&1][y&1].sum(id(x),id(y));
} LL get(int u,int v,int x,int y){
return get(x,y)^get(u-1,v-1)^get(x,v-1)^get(u-1,y);
} void add(int x,int y,LL d){
C[x&1][y&1].add(id(x),id(y),d);
} void add(int u,int v,int x,int y,LL d){
add(x+1,y+1,d); add(u,v,d); add(x+1,v,d); add(u,y+1,d);
} int main(){ int i,kd,u,v,x,y; LL d;
n=ri(),m=ri(); while(m--){
kd=ri(),u=ri(),v=ri(),x=ri(),y=ri();
if(kd==1) printf("%lld\n",get(u,v,x,y));
else{
d=rl();//
add(u,v,x,y,d);
}
} return 0;
}

最新文章

  1. ubuntu14.04 JDK安装
  2. Android沉浸式(侵入式)标题栏(状态栏)Status(三)
  3. 九度OJ做题记录 更新.....
  4. poj2478
  5. GPL,LGPL和BSD等协议注意事项
  6. silverlight游戏在坑内发展
  7. SpringMVC 异常处理
  8. 商城项目整理(三)JDBC增删改查
  9. Spark入门(1-4)安装、运行Spark
  10. C语言语法
  11. Mac 上有哪些鲜为人知且极大提高效率的工具?
  12. Docker 从入门到放弃(一)安装
  13. TNS:listener does not currently know of service requested in connect descriptor错误改正
  14. [No0000124]WPF 扩展控件Behavior的几种方式
  15. c# HttpWebRequest Cookie 设置到 webBrowser 控件
  16. bzoj 4842: [Neerc2016]Delight for a Cat
  17. drill 试用
  18. HDOJ:6333-Problem B. Harvest of Apples(组合数学+莫队算法+逆元)
  19. Epoll模型讲解
  20. 解决在cmder中bash(WSL)上下箭头不能使用问题

热门文章

  1. FreeRTOS的学习路线
  2. thinkphp 3.2.3 - Route.class.php 解析(路由匹配)
  3. python3 练习题100例 (七)
  4. 离线安装 Visual Studio Express 而不下载整个镜像文件的方法(转载)
  5. 华东交通大学2018年ACM“双基”程序设计竞赛 D
  6. python集成开发环境PyCharm
  7. itchat 总结(转)
  8. AutoMapper教程
  9. 37、iamgeview 图层叠加
  10. IOS开发学习笔记033-UIScrollView