【题目描述】
小a正在玩一款即时战略游戏,现在他要用航空母舰对敌方阵地进行轰炸
地方阵地可以看做是n×m的矩形
航空母舰总共会派出q架飞机。
飞机有两种,第一种飞机会轰炸以(xi,yi)为中心,对角线长为li的正菱形(也就是两条对角线分别于x轴y轴平行的正方形),而第二种飞机只会轰炸正菱形的上半部分(包括第xi行)
(具体看样例解释)
现在小a想知道所有格子被轰炸次数的异或和
注意:不保证被轰炸的格子一定在矩形范围内,若越界请忽略【输入描述】
第一行三个整数n,m,q,分别表示矩阵的长/宽/询问次数
接下来q行,每行四个整数opt,x,y,l,表示飞机类型,轰炸的坐标,以及对角线长度
保证l为奇数!【输出描述】
一个整数,表示所有格子被轰炸次数的异或和
【样例】
示例1
输入
4 5 4
1 2 2 1
1 3 3 5
1 3 2 3
2 2 4 3
输出
2
思路:
由于 n, m 只有 1000,且没有修改操作,根据题意可以考虑进行二维差分
由于是菱形,不便于直接操作,因此可以将菱形分为上下两部分,对于上半部分来说:把标记分为向左下放、向右下放两种,首先在最顶端打上 +1 的标记,再分别在最下端的两边打上 -1 的标记,每次分别下放即可
由于容易越界,因此可以对所有的操作都加上偏移量,最后最后只统计原矩形的贡献
【源代码】
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<deque>
#include<vector>
#include<set>
#include<map>
#define PI acos(-1.0)
#define E 1e-6
#define INF 0x3f3f3f3f
#define N 3001
#define LL long long
const int MOD=1e9+7;
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
using namespace std;
const int base=1000;
int a[N][N];//a[][]为左下方延伸
int b[N][N];//b[][]为右下方延伸
void up(int x,int y,int l){
a[x-l/2][y]++;//左下方延伸
b[x-l/2][y+1]--;//右下方延伸
a[x+1][y-l/2-1]--;//隔断
b[x+1][y+l/2+2]++;//隔断
}
void down(int x,int y,int l){
a[x+1][y+l/2]--;//左下方延伸
b[x+1][y-l/2+1]++;//右下方延伸
b[x+l/2+1][y+1]--;//隔断
a[x+l/2+1][y]++;//隔断
}
int main (){
int n,m,q;
cin>>n>>m>>q;
int opt,x,y,l;
while(q--){
cin>>opt>>x>>y>>l;
x+=base;
y+=base;
if(opt==1)
down(x,y,l);
up(x,y,l);
}
int res=0;
for(int i=1;i<=n+2*base;i++){//+2*base防溢出
int temp=0;
for(int j=1;j<=m+2*base;j++){
temp+=a[i][j]+b[i][j];
if(i<=base+n && i>base && j<=base+m && j>base)
res^=temp;
a[i+1][j-1]+=a[i][j];
b[i+1][j+1]+=b[i][j];
}
}
cout<<res<<endl;
return 0;
}