hdu2642二维树状数组单点更新+区间查询

http://acm.hdu.edu.cn/showproblem.php?pid=2642

题目大意:一个星空,二维的.上面有1000*1000的格点,每个格点上有星星在闪烁.一开始时星星全部暗淡着,有Q个操作:

B x y 点亮一盏星星

D x y 熄灭一盏星星

Q fx tx fy ty 查询这个矩形里面亮着的星星的个数.


题解:首先,注意输入的x,y可能是(0,0),这样一来,用树状数组就不好维护了,所以将之平移一个单位,每当读入一对坐标,要进行x++,y++..

其次,输入的查询,矩形的fx,tx大小未定,所以用:if(fx>tx)swap(fx,tx);进行判断一下

最后,星星点亮了可能还会再次点亮,所以需要加上一个状态数组进行判断.


#include<iostream>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define ll long long  
#define re(i,n) for(int i=0;i<n;i++)      
const int maxn = 1007;
int a[maxn][maxn];
bool sta[maxn][maxn];
int lowbit(int x){
	return x&-x;
}
void update(int x, int y, int d){
	for (int i = x; i < maxn; i+=lowbit(i)){
		for (int j = y; j < maxn; j+=lowbit(j)){
			a[i][j] += d;
		}
	}
}
int query(int x, int y){
	int ans = 0;
	for (int i = x; i>0; i -= lowbit(i)){
		for (int j = y; j>0; j -= lowbit(j)){
			ans += a[i][j];
		}
	}
	return ans;
}
int main(){
	freopen("in.txt", "r", stdin);  
	int q; cin >> q;
	memset(a, 0, sizeof(a)), memset(sta, 0, sizeof(sta));
	while (q--){
		char op[2]; scanf("%s", op);
		if (op[0] == 'Q'){
			int fx, fy, tx, ty; scanf("%d%d%d%d", &fx, &tx, &fy, &ty);
			fx++, fy++, tx++, ty++;
			if (fx>tx)swap(fx, tx); if (fy > ty)swap(fy, ty);
			fx--, fy--;
			int ans = query(tx, ty) + query(fx, fy) - query(tx, fy) - query(fx, ty);
			printf("%d
", ans);
		}
		else{
			int x, y; scanf("%d%d", &x, &y); x++, y++;
			if (op[0] == 'B'){
				if (sta[x][y])continue;
				update(x, y, 1), sta[x][y] = 1;
			}
			else{
				if (sta[x][y] == false)continue;
				update(x, y, -1), sta[x][y] = 0;
			} 
		}
	}
	return 0;
}