打鼹鼠 contest 树状数组练习 T7

Description

在一个“打鼹鼠”的游戏中,鼹鼠会不时地从洞中钻出来,不过不会从洞口钻进去(鼹鼠真胆大……)。洞口都在一个大小为n(n<=1024)的正方形中。这个正方形在一个平面直角坐标系中,左下角为(0,0),右上角为(n-1,n-1)。洞口所在的位置都是整点,就是横纵坐标都为整数的点。而SuperBrother也不时地会想知道某一个范围的鼹鼠总数。这就是你的任务。


Input

第一行,一个数n,表示鼹鼠的范围。以后每一行开头都有一个数m,表示不同的操作:
m=1,x,y,k(0<=x,y<n),表示在点(x,y)处新出现了k只鼹鼠;
m=2,x1,y1,x2,y2(0<=x1<=x2<n,0<=y1<=y2<n),表示询问矩形(x1,y1)-(x2,y2)内的鼹鼠数量;
m=3,表示老师来了,不能玩了。保证这个数会在输入的最后一行。


Output

对于每个m=2,输出一行数,这行数只有一个数,即所询问的区域内鼹鼠的个数。


Hint

询问数不会超过10000,鼹鼠数不会超过maxlongint。n<=3000。


Solution

二维树状数组,维护单点修改维护一段区间和。修改和查询前缀和都很简单,跟一维都是一个思路,就是多套了一重循环,然后查询一个矩阵的和的时候,可以画个图,公式就是dofinD(xx,yy)-dofinD(x,yy)-dofinD(xx,y)+dofinD(x,y)。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define lowbit(x) (x&(-x))
#define maxn 3005
#define int long long
using namespace std;
int c[maxn][maxn];
int n,x,y,xx,yy,flag;
void doadd(int x,int y,int dd){
	while(x<=n){
		for(int i=y;i<=n;i+=lowbit(i)){
			c[x][i]+=dd;
		}
		x+=lowbit(x);
	}
}
int dofinD(int x,int y){
	int ans=0;
	while(x>0){
		for(int i=y;i>0;i-=lowbit(i)){
			ans+=c[x][i];
		}
		x-=lowbit(x);
	}
	return ans;
}
int doFind(int x,int y,int xx,int yy){
	x--,y--;
	return dofinD(xx,yy)-dofinD(x,yy)-dofinD(xx,y)+dofinD(x,y);
}
signed main(){
	scanf("%d",&n);
	while(1){
		scanf("%d",&flag);
		if(flag==3)break;
		if(flag==1){
			scanf("%d%d%d",&x,&y,&xx);
			x++,y++;
			doadd(x,y,xx);
		}
		else if(flag==2){
			scanf("%d%d%d%d",&x,&y,&xx,&yy);
			x++,y++,xx++,yy++;
			printf("%d\n",doFind(x,y,xx,yy));
		}
	}
	return 0;
}
posted @ 2018-11-30 17:24  虚拟北方virtual_north。  阅读(183)  评论(0编辑  收藏  举报