(二维树状数组)poj 1195 Mobile phones & poj 2155 Matrix

poj1195

题意:
一个二维矩阵,有如下操作:
0 S:创建一个S * S的二维矩阵
1 x y v:在点 [ x , y ] 的值加上 v
2 x1 y1 x2 y2:计算在区间 [ x1 , y1] ~ [ x2 , y2 ] 中所有点的和
3:结束

poj2155

题意:
一个二维矩阵,有如下操作:
C x1 y1 x2 y2:在区间 [ x1 , y1] ~ [ x2 , y2 ] 的值取反(即1→0, 0→1)
Q x y:查询 点[ x , y ] 的值

思路:
二维树状数组的查找与添加

另一种思路:二维线段树写法

注意:
二维树状数组的更新方式有两种:

1.查询是区间 [ xl, xr ] [yl, yr] ,更新的是点[ x ] [y]
as:在 点[ 2 ][ 4 ] 更新

(更新范围)
[ 2 ] [ 4 ] → [ 2 ] [ n ]

点更新和求和的代码和一维的树状数组一样,查询代码有所不同
比如要查询点[ x1 ] [ y1 ] → 点 [ x2 ] [ y2 ] 的区间:

ans = 0;
for (int i = x1; i <= x2; i++)
		ans = ans - sum(i, y1-1) + sum(i, y2);

2.查询的是点 [ x ] [y], 更新的是区间 [ xl, xr ] [yl, yr]
as:在点[ 2 ] [ 3 ] → 点 [ 4 ] [ 5 ] 的区间

(更新范围)
 [ 4 ] [ 5 ] → [ n ] [ n ]
 [ 4 ] [ 3 ] → [ n ] [ n ]
 [ 2 ] [ 5 ] → [ n ] [ n ]
 [ 2 ] [ 3 ] → [ n ] [ n ]

区间更新代码:

void add(int x, int y, int d){
	int temp = y;
	while (x <= final){
		y = temp;
		while (y <= final){
			tree[x][y] += d;
			y += lowbit(y);
		}
		x += lowbit(x);
	}
}

在点[ x1 ] [ y1 ] → 点 [ x2 ] [ y2 ] 的区间更新:

add(x2+1, y2+1, 1);  
add(x2+1, y1, 1);  
add(x1, y2+1, 1);  
add(x1, y1, 1);

//or

add(x2+1, y2+1, 1); 
add(x1, y2+1, 1); 
add(x2+1, y1, 1);  
add(x1, y1, 1);

求和的代码:

int sum(int x, int y){
	int cnt = 0, temp = y;
	while (x > 0){
		y = temp;
		while (y > 0){
			cnt += tree[x][y];
			y -= lowbit(y);
		}
		x -= lowbit(x);
	}
	return cnt;
}

poj 1195代码

#include <iostream>
using namespace std; 
const int MAXN = 1030;
#define lowbit(x) ((x) & -(x))
int tree[MAXN][MAXN];
int final;
void add(int x, int y, int d){
	while (y <= final){
		tree[x][y] += d;
		y += lowbit(y);
	}
}
int sum(int x, int y){
	int sum = 0;
	while (y > 0){
		sum += tree[x][y];
		y -= lowbit(y);
	}
	return sum;
}
int main(){
	int n, a, b, c, d, ans;
    while (~scanf("%d", &n) && n != 3){
    	if (n == 0){
    		scanf("%d", &final);
    		final++;
		}
    	else if (n == 1){
    		scanf("%d%d%d", &a, &b, &c);
    		add(a+1, b+1, c);
		}
		else if (n == 2){
			scanf("%d%d%d%d", &a, &b, &c, &d);
			a++;
			c++;
			b++;
			d++;
			ans = 0;
			for ( ; a <= c; a++)
				ans = ans - sum(a, b-1) + sum(a, d);
			printf("%d\n", ans);
		}
    }
    return 0;
}

poj 2155 代码

#include <iostream>
#include <algorithm>
#include <cstring>
#define lowbit(a) ((a) & (-a))
using namespace std;
const int MAXN = 1010;
int tree[MAXN][MAXN];  //记录取反次数
int final;
void add(int x, int y, int d){
	int temp = y;
	while (x <= final){
		y = temp;
		while (y <= final){
			tree[x][y] += d;
			y += lowbit(y);
		}
		x += lowbit(x);
	}
}
int sum(int x, int y){
	int cnt = 0, temp = y;
	while (x > 0){
		y = temp;
		while (y > 0){
			cnt += tree[x][y];
			y -= lowbit(y);
		}
		x -= lowbit(x);
	}
	return cnt;
}
int main(){
    int t, m, a, b, c, d;
    char op;
    scanf("%d", &t);
    while (t--){
    	scanf("%d%d", &final, &m);
    	memset(tree, 0, sizeof(tree));
    	while (m--){
			scanf(" %c", &op);
	    	if (op == 'C'){
	    		scanf("%d%d%d%d", &a, &b, &c, &d);
	    		add(c+1, d+1, 1);
	    		add(c+1, b, 1);
	    		add(a, d+1, 1);
	    		add(a, b, 1);
			}
			else{
				scanf("%d%d", &a, &b);
				printf("%d\n", sum(a, b) % 2);
			}
		}
		printf("\n");
	}
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值