链接:https://ac.nowcoder.com/acm/contest/317/E
来源:牛客网
题目描述
小a正在玩一款即时战略游戏,现在他要用航空母舰对敌方阵地进行轰炸
地方阵地可以看做是n×mn×m的矩形
航空母舰总共会派出qq架飞机。
飞机有两种,第一种飞机会轰炸以(xi,yi)(xi,yi)为中心,对角线长为lili的正菱形(也就是两条对角线分别于xx轴 yy轴平行的正方形),而第二种飞机只会轰炸正菱形的上半部分(包括第xixi行)
(具体看样例解释)
现在小a想知道所有格子被轰炸次数的异或和
注意:不保证被轰炸的格子一定在矩形范围内,若越界请忽略
地方阵地可以看做是n×mn×m的矩形
航空母舰总共会派出qq架飞机。
飞机有两种,第一种飞机会轰炸以(xi,yi)(xi,yi)为中心,对角线长为lili的正菱形(也就是两条对角线分别于xx轴 yy轴平行的正方形),而第二种飞机只会轰炸正菱形的上半部分(包括第xixi行)
(具体看样例解释)
现在小a想知道所有格子被轰炸次数的异或和
注意:不保证被轰炸的格子一定在矩形范围内,若越界请忽略
输入描述:
第一行三个整数n,m,qn,m,q,分别表示矩阵的长/宽/询问次数
接下来qq行,每行四个整数opt,x,y,lopt,x,y,l,表示飞机类型,轰炸的坐标,以及对角线长度
保证ll为奇数!
输出描述:
一个整数,表示所有格子被轰炸次数的异或和
示例1
输入
4 5 4
1 2 2 1
1 3 3 5
1 3 2 3
2 2 4 3
输出
2
题意:每次对一个菱形区域轰炸,求每个点被轰炸次数的异或和。
题解:如果是矩形,很容易利用差分+二维前缀和解决(差分主要用于区间修改问题,前缀和主要用于单点查询问题),但是由于是矩形,单点查询并不能通过简单的加减进行维护,
于是动态差分诞生了,由于单点查询是按照行列顺序进行的,所以可以让差分数组不断地向下向右转移,具体见下图
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
typedef long long ll;
int a[][],b[][],c[][],d[][];
void up(int x,int y,int l){
a[x-(l/)][y]++;b[x-(l/)][y+]--;
a[x+][y-(l/)-]--;b[x+][y+(l/)+]++;
}
void down(int x,int y,int l){
c[x+][y-(l/)+]++;d[x+][y+(l/)]--;
c[x++(l/)][y+]--;d[x+(l/)+][y]++;
}
int main(){
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
while(q--){
int opt,x,y,l;
scanf("%d%d%d%d",&opt,&x,&y,&l);
up(x+,y+,l);
if(opt==)down(x+,y+,l);
}
int ans0=;
for(int i=;i<=n+;i++){
int ans=;
for(int j=;j<=;j++){
ans+=a[i][j]+b[i][j]+c[i][j]+d[i][j];
if(i>&&j>&&j<=+m){
ans0^=ans;
}
if(i+<&&j->=){
a[i+][j-]+=a[i][j];
d[i+][j-]+=d[i][j];
}
if(i+<&&j+<){
b[i+][j+]+=b[i][j];
c[i+][j+]+=c[i][j];
}
}
}
cout<<ans0<<endl;
return ;
}