小a的轰炸游戏

【题目描述】

小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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值