POJ - 1195 Mobile phones 二维树状数组 / 线段树

本文详细介绍了一种解决二维矩阵中手机数量动态更新与查询的问题,通过使用树状数组和线段树两种数据结构实现高效操作。具体包括如何在矩阵中增加手机数量,以及如何查询特定矩形区域内的总手机数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://vjudge.net/problem/POJ-1195

有一个正方形区域S*S(1<=S<=1024)。含有很多小区域,小区域编号从0开始,直到S-1。每一个单位各是一个区域,每个区域上有一定数量的手机,同时每一个区域上的手机的数目也是不断变化的,现在要一边进行修改某些单位格子内的手机的数目,同时也要询问某些区域的手机数目。 数据保证每个格子内手机数目一直在int范围内,查询的区域内的手机数目也在int范围内

Input

有多组数据,每一行先输入一个数字x,如果x=0再输入S,表示区域的大小,并且所有的区域内都没有手机:如果x=1,接着输入x,y,a,表示坐标(x,y)的这个小格内增加a个手机:如果x=2,接着输入x1,y1,x2,y2.表示要查询的矩形区域的左上角坐标和右下角坐标,如果x=3,程序结束。

Output

对于每次查询,输出这个区域内的手机数目。

Sample Input

0 4
1 1 2 3
2 0 0 2 2 
1 1 1 2
1 1 2 -1
2 1 1 2 3 
3

Sample Output

3
4

线段树:4倍的开不了,开3倍就好

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
#define lowbit(x) (x & (-x))
#define INF 0x3f3f3f3f
const int N = 1055;
int n, m;
int sum[N * 3][N * 3];
void updatey(int y, int l, int r, int cur, int p, int op, int val) {
	if(l == r) {
		if(op == 1) sum[p][cur] += val;
		else sum[p][cur] = sum[p << 1][cur] + sum[p << 1 | 1][cur];
		return;
	}
	int mid = (r + l) >> 1;
	if(y <= mid)updatey(y, l, mid, cur << 1, p, op, val);
	else updatey(y, mid + 1, r, cur << 1 | 1, p, op, val);
	sum[p][cur] = sum[p][cur << 1] + sum[p][cur << 1 | 1];
}

void updatex(int x, int y, int l, int r, int cur, int val) {
	if(l == r) {
		updatey(y, 1, n, 1, cur, 1, val);
		return;
	}
	int mid = (l + r) >> 1;
	if(x <= mid) updatex(x, y, l, mid, cur << 1, val);
	else updatex(x, y, mid + 1, r, cur << 1 | 1, val);
	updatey(y, 1, n, 1, cur, 2, val); 
}
int queryy(int ly, int ry, int l, int r, int cur , int p) {
	if(ly <= l && r <= ry) {
		return sum[p][cur];
	}
	int res = 0;
	int mid = (l + r) >> 1;
	if(ly <= mid) res += queryy(ly, ry, l, mid, cur << 1, p);
	if(ry > mid) res += queryy(ly, ry, mid + 1, r, cur << 1 | 1, p); 
	return res;
}
int queryx(int lx, int rx, int ly, int ry, int l, int r, int cur) {
	int res = 0;
	if(lx <= l && r <= rx) {
		res = queryy(ly, ry, 1, n, 1, cur);
		return res;
	}
	int mid = (l + r) >> 1;
	if(lx <= mid) res += queryx(lx, rx, ly, ry, l, mid, cur << 1);
	if(rx > mid) res += queryx(lx, rx, ly, ry, mid + 1, r, cur << 1 | 1);
	return res; 
}
int main() {
	int T;
	char op[2];
	int x1, x2, y1, y2;
	int val;
	while(~scanf("%d", &m) && m != 3) {
		if(m == 0) {
			scanf("%d", &n);
			n++;
			memset(sum, 0, sizeof(sum));
		} else if(m == 1) {
			scanf("%d %d %d", &x1, &y1, &val);
			x1++, y1++;
			updatex(x1, y1, 1, n, 1, val);
		} else {
			scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
			x1++; x2++; y1++; y2++;
			printf("%d\n", queryx(x1, x2, y1, y2, 1, n, 1));
		}
	}
	return 0;
}

树状数组:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define lowbit(x) (x&(-x))
const int N=1305;
typedef long long ll;
int sum[N][N];
int n,m;

void add(int x,int y,int val)
{
	for(int i=x;i<=n+1;i+=lowbit(i))
		for(int j=y;j<=n+1;j+=lowbit(j))
			sum[i][j]+=val;
}
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+=sum[i][j];
	return ans;
}
int main()
{
    while(~scanf("%d%d",&m,&n))
    {
    	int op;
    	int l,r,val,x1,x2,y1,y2;
    	memset(sum,0,sizeof(sum));
    	while(scanf("%d",&op)&&op!=3)
    	{
    		if(op==1)
    		{
    			scanf("%d%d%d",&x1,&y1,&val);
    			x1++,y1++;
    			add(x1,y1,val);
			}
			else
			{
				scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
				x1++,x2++,y1++,y2++;
				printf("%d\n",query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1));
			}
		}
	}
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值