POJ 1195 Mobile phones

链接:http://poj.org/problem?id=1195


Mobile phones
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 16646   Accepted: 7653

Description

Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The squares form an S * S matrix with the rows and columns numbered from 0 to S-1. Each square contains a base station. The number of active mobile phones inside a square can change because a phone is moved from a square to another or a phone is switched on or off. At times, each base station reports the change in the number of active phones to the main base station along with the row and the column of the matrix.

Write a program, which receives these reports and answers queries about the current total number of active mobile phones in any rectangle-shaped area.

Input

The input is read from standard input as integers and the answers to the queries are written to standard output as integers. The input is encoded as follows. Each input comes on a separate line, and consists of one instruction integer and a number of parameter integers according to the following table. 

The values will always be in range, so there is no need to check them. In particular, if A is negative, it can be assumed that it will not reduce the square value below zero. The indexing starts at 0, e.g. for a table of size 4 * 4, we have 0 <= X <= 3 and 0 <= Y <= 3.

Table size: 1 * 1 <= S * S <= 1024 * 1024
Cell value V at any time: 0 <= V <= 32767
Update amount: -32768 <= A <= 32767
No of instructions in input: 3 <= U <= 60002
Maximum number of phones in the whole table: M= 2^30 

Output

Your program should not answer anything to lines with an instruction other than 2. If the instruction is 2, then your program is expected to answer the query by writing the answer as a single line containing a single integer to standard 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


Source

IOI 2001

大意——给你一个n*n矩阵的区域,它的行列下标都是从0开始的。每个矩阵元素代表一个基站,基站内的处于运行中的手机数量因为各种原因会不断变化。各个基站会不定期地向主基站报告,以便统计运行中的手机数量。你的任务是根据相应的命令完成相应的操作。其中主要的就是更新某一个矩阵元素的值和一个区域的矩阵元素值之和。


思路——很显然这是一个裸的二维树状数组的题。其操作就是更新某一个值和区间求和。因此,我们直接用一维树状数组推广过来即可解决问题。注意:矩阵元素下标从0开始。


复杂度分析——时间复杂度:O((log(n))^2),空间复杂度:O(n^2)


附上AC代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//#pragma comment(linker, "/STACK:102400000, 102400000")
using namespace std;
typedef unsigned int li;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const double pi = acos(-1.0);
const double e = exp(1.0);
const double eps = 1e-8;
const int maxn = 1030;
int mat[maxn][maxn];
int order; // 键入命令
int n; // 数组大小

int lowbit(int x); // 求2^k,k表示x为二进制时末尾的零的个数
void update(int x, int y, int add); // 更新状态
int sum(int x, int y); // 求和

int main()
{
	ios::sync_with_stdio(false);
	int x1, y1, x2, y2, add, ans;
	while (scanf("%d", &order)==1 && 3!=order)
	{
		switch(order)
		{
			case 0:
				scanf("%d", &n);
				memset(mat, 0, sizeof(mat)); // 初始化为0
				break;
			case 1:
				scanf("%d%d%d", &x1, &y1, &add);
				update(x1+1, y1+1, add); // x,y可能为0,所以加1,后面类似
				break;
			case 2:
				scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
				ans = 0;
				ans += sum(x2+1, y2+1); // 总求和
				ans -= sum(x2+1, y1);
				ans -= sum(x1, y2+1); // 去掉多余部分
				ans += sum(x1, y1); // 多减掉一部分,加回来,画图可知
				printf("%d\n", ans);
				break;
			default:
				printf("INPUT ERROR!\n");
				break;
		}
	}
	return 0;
}

int lowbit(int x)
{
	return (x&(-x));
}

void update(int x, int y, int add)
{ // x,y表示矩阵下标,此功能是把下标为x,y的数加上add
	for (int i=x; i!=0&&i<=n; i+=lowbit(i))
		for (int j=y; j!=0&&j<=n; j+=lowbit(j))
			mat[i][j] += add;
}

int sum(int x, int y)
{ // x,y表示矩阵下标,此功能是把下标小于x,y的矩阵元素值加起来
	int res = 0;
	for (int i=x; i>0; i-=lowbit(i))
		for (int j=y; j>0; j-=lowbit(j))
			res += mat[i][j];
	return res;
}


你可能感兴趣的:(树状数组)