1. 程式人生 > >小a的轟炸遊戲(差分,前綴和)

小a的轟炸遊戲(差分,前綴和)

== click art fine details display type -- isp

題目傳送門

題意:

給出一個n*m的矩形,然後有兩個操作.

1操作,對一個給出的菱形,對菱形範圍內的東西進行+1。

2操作,對一個上半菱形的區域,進行+1操作。

最後求矩形內各個數的異或和。

思路:

在矩形中,我們在四個角上進行++--,然後利用差分的性質,就解決了區間更新,

但是在這裏,想破腦汁,也沒想出怎麽進行++--。因為矩形的差分是橫著或者豎著的,

最後的求和非常容易,但是這裏不一樣。最後看了題解豁然大悟,原來差分還可以動態的來,

本行的差分數組使用完了,還可以把差分數組下傳,繼續在下一層繼續起到作用,這是神奇的操作。
技術分享圖片

代碼:

技術分享圖片
#include<bits/stdc++.h>
using
namespace std; typedef long long ll; #define N 3005 #define L 1000 int n,m,q; int a[N][N],b[N][N],c[N][N],d[N][N]; int bb[N][N]; void up(int x,int y,int l) { a[x-l/2][y]++;a[x+1][y-l/2-1]--; b[x-l/2][y+1]--;b[x+1][y+l/2+2]++; } void down(int x,int y,int l) { c[x+1][y-l/2+1]++;c[x+l/2
+1][y+1]--; d[x+1][y+l/2]--;d[x+l/2+1][y]++; } int main() { while(~scanf("%d %d %d",&n,&m,&q)) { /*memset(a,0,sizeof(a)); memset(b,0,sizeof(a)); memset(c,0,sizeof(a)); memset(d,0,sizeof(a));*/ while(q--) { int op;
int x,y,l; scanf("%d %d %d %d",&op,&x,&y,&l); x+=L,y+=L; up(x,y,l); if(op==1) down(x,y,l); } int ans=0; for(int i=0;i<n+2*L;i++) { int cnt=0; for(int j=0;j<m+2*L;j++) { cnt+=a[i][j]+b[i][j]+c[i][j]+d[i][j]; if(i>=L+1&&i<=L+n&&j>=L+1&&j<=m+L){ ans^=cnt;//bb[i-L][j-L]=cnt; } a[i+1][j-1]+=a[i][j]; b[i+1][j+1]+=b[i][j]; c[i+1][j+1]+=c[i][j]; d[i+1][j-1]+=d[i][j]; } } /* for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cout<<bb[i][j]<<" "; } cout<<endl; }*/ printf("%d\n",ans); } return 0; }
View Code

參考:https://blog.csdn.net/qq_41289920/article/details/86683583

小a的轟炸遊戲(差分,前綴和)