zoukankan      html  css  js  c++  java
  • [动态差分+二维前缀和][小a的轰炸游戏]

    链接:https://ac.nowcoder.com/acm/contest/317/E
    来源:牛客网

    题目描述

    小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
    题意:每次对一个菱形区域轰炸,求每个点被轰炸次数的异或和。
    题解:如果是矩形,很容易利用差分+二维前缀和解决(差分主要用于区间修改问题,前缀和主要用于单点查询问题),但是由于是矩形,单点查询并不能通过简单的加减进行维护,
    于是动态差分诞生了,由于单点查询是按照行列顺序进行的,所以可以让差分数组不断地向下向右转移,具体见下图
     1 #include<iostream>
     2 #include<string>
     3 #include<algorithm>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<cstring>
     7 using namespace std;
     8 typedef long long ll;
     9 int a[3019][3019],b[3019][3019],c[3019][3019],d[3019][3019];
    10 void up(int x,int y,int l){
    11     a[x-(l/2)][y]++;b[x-(l/2)][y+1]--;
    12     a[x+1][y-(l/2)-1]--;b[x+1][y+(l/2)+2]++;
    13 }
    14 void down(int x,int y,int l){
    15     c[x+1][y-(l/2)+1]++;d[x+1][y+(l/2)]--;
    16     c[x+1+(l/2)][y+1]--;d[x+(l/2)+1][y]++;
    17 }
    18 int main(){
    19     int n,m,q;
    20     scanf("%d%d%d",&n,&m,&q);
    21     while(q--){
    22         int opt,x,y,l;
    23         scanf("%d%d%d%d",&opt,&x,&y,&l);
    24         up(x+1000,y+1000,l);
    25         if(opt==1)down(x+1000,y+1000,l);
    26     }
    27     int ans0=0;
    28     for(int i=0;i<=n+1000;i++){
    29         int ans=0;
    30         for(int j=0;j<=3000;j++){
    31             ans+=a[i][j]+b[i][j]+c[i][j]+d[i][j];
    32             if(i>1000&&j>1000&&j<=1000+m){
    33                 ans0^=ans;
    34             }
    35             if(i+1<3019&&j-1>=0){
    36                 a[i+1][j-1]+=a[i][j];
    37                 d[i+1][j-1]+=d[i][j];
    38             }
    39             if(i+1<3019&&j+1<3019){
    40                 b[i+1][j+1]+=b[i][j];
    41                 c[i+1][j+1]+=c[i][j];
    42             }
    43         }
    44     }
    45     cout<<ans0<<endl;
    46     return 0;
    47 }
    View Code
     
  • 相关阅读:
    ip报文
    常见端口
    navicat15 破解版
    谷歌跨域设置
    CSS flex弹性布局来做 页面底部自适应:页面高度不足时,在底部显示;页面高度超出时,随页面滚动(亲测有效)
    phpstorm 2019 激活码
    aes cbc模式
    Vue的安装及使用快速入门
    从SVN服务器端彻底删除错误提交版本
    Nginx配置https和wss
  • 原文地址:https://www.cnblogs.com/MekakuCityActor/p/10561113.html
Copyright © 2011-2022 走看看