1. 程式人生 > >二維樹狀數組復習—— SuperBrother打鼴鼠

二維樹狀數組復習—— SuperBrother打鼴鼠

cst amp 整數 大小為n 不同 del ostream oid esp

在這個“打鼴鼠”的遊戲中,鼴鼠會不時地從洞中鉆出來,不過不會從洞口鉆進去(鼴鼠真膽大……)。洞口都在一個大小為n(n< =1024)的正方形中。這個正方形在一個平面直角坐標系中,左下角為(0,0),右上角為(n-1,n-1)。洞口所在的位置都是整點,就是橫縱坐標都為整數的點。而SuperBrother也不時地會想知道某一個範圍的鼴鼠總數。這就是你的任務。

輸入

每個輸入文件有多行。 第一行,一個數n,表示鼴鼠的範圍。 以後每一行開頭都有一個數m,表示不同的操作: m=1,那麽後面跟著3個數x,y,k(0< =x,y< n),表示在點(x,y)處新出現了k只鼴鼠; m=2,那麽後面跟著4個數x1,y1,x2,y2(0< =x1< =x2< n,0< =y1< =y2< n),表示詢問矩形(x1,y1)-(x2,y2)內的鼴鼠數量; m=3,表示老師來了,不能玩了。保證這個數會在輸入的最後一行。 詢問數不會超過10000,鼴鼠數不會超過maxlongint。

輸出

對於每個m=2,輸出一行數,這行數只有一個數,即所詢問的區域內鼴鼠的個數。

樣例輸入

4
1 2 2 5
2 0 0 2 3
3

樣例輸出

5

提示

水題一道。 所有數據均為隨機生成,包括樣例……

題目很好懂,暴力可以水。為復習寫了二維樹狀數組。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 1025
#define
lowbit(x) x&(-x) int d[4][maxn][maxn],n; int getsum(int id,int x,int y) { int sum=0; for(int i=x;i;i-=lowbit(i)) for(int j=y;j;j-=lowbit(j)) sum+=d[id][i][j]; return sum; } int ask(int x,int y) { return (getsum(0,x,y)*(x+1)*(y+1)-(y+1)*getsum(1,x,y)-(x+1
)*getsum(2,x,y)+getsum(3,x,y)); } void U(int id,int x,int y,int del) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) d[id][i][j]+=del; } void modify(int x,int y,int c) { U(0,x,y,c);U(0,x+1,y,-c);U(0,x,y+1,-c);U(0,x+1,y+1,c); U(1,x,y,x*c);U(1,x+1,y,-(x+1)*c);U(1,x,y+1,-x*c);U(1,x+1,y+1,(x+1)*c); U(2,x,y,y*c);U(2,x+1,y,-y*c);U(2,x,y+1,-(y+1)*c);U(2,x+1,y+1,(y+1)*c); U(3,x,y,x*y*c);U(3,x+1,y,-(x+1)*y*c);U(3,x,y+1,-x*(y+1)*c);U(3,x+1,y+1,(x+1)*(y+1)*c); } int main() { scanf("%d",&n); int pattern; while(scanf("%d",&pattern)&&pattern!=3) { if(pattern==1) { int x,y,c; scanf("%d %d %d",&x,&y,&c); x++,y++; modify(x,y,c); }else { int a,b,c,d; scanf("%d %d %d %d",&a,&b,&c,&d); a++,b++,c++,d++; int ans=ask(c,d)-ask(a-1,d)-ask(c,b-1)+ask(a-1,b-1); printf("%d\n",ans); } } }

二維樹狀數組復習—— SuperBrother打鼴鼠