【POJ1195】【二维树状数组】Mobile phones

本文介绍了一种使用二维树状数组解决矩形区域活动手机数量统计问题的方法。通过更新单元格值并查询任意矩形区域内元素总和,高效处理大量更新与查询指令。适用于竞赛编程与大规模数据处理。

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

【分析】

不说了,最基本的二维树状数组

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #include <utility>
 7 #include <iomanip>
 8 #include <string>
 9 #include <cmath>
10 #include <map>
11 
12 const int MAXN = 100000 * 2  +  10; 
13 const int N=1050;
14 using namespace std;
15 
16 int n, array[N][N];
17 
18 int lowbit(int x){return x & (-x);}
19 void add(int i, int j, int w) {
20     int tmp;
21     while(i <= n){
22         tmp=j;
23         while(tmp <= n){
24             array[i][tmp] += w;
25             tmp += lowbit(tmp);
26         }
27         i += lowbit(i);
28     }
29 }
30 
31 int sum(int i, int j){
32     int tmp, ans=0;
33     while(i > 0){
34         tmp=j;
35         while(tmp > 0){
36             ans += array[i][tmp];
37             tmp -= lowbit(tmp);
38         }
39         i -= lowbit(i);
40     }
41     return ans;
42 }
43 
44 int main(){
45     #ifdef LOCAL
46     freopen("data.txt",  "r",  stdin);
47     freopen("out.txt",  "w",  stdout); 
48     #endif 
49     int op, x1, y1, x2, y2, w;
50     memset(array, 0, sizeof(array));
51     while( ~scanf("%d", &op) ){
52         if(op == 0){
53             scanf("%d", &n);
54             n++;
55         }else if(op == 1){
56             scanf("%d%d%d", &x1, &y1, &w);
57             add(x1 + 1, y1 + 1, w);
58         }else if(op == 2){
59             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
60             int ans=sum(x2 + 1, y2 + 1) - sum(x1, y2 + 1) - sum(x2 + 1, y1) + sum(x1, y1);
61             printf("%d\n", ans);
62         }else if(op == 3)
63             break;
64     }
65     return 0;
66 }
View Code

 

转载于:https://www.cnblogs.com/hoskey/p/4319894.html

<think>好的,我现在需要帮助用户了解二维树状数组的实现和应用。首先,我得回顾一下用户之前的提问和引用内容,确保回答符合他们的需求。用户提到了二维树状数组,引用中也有关于二维前缀和、单点修改以及例题的信息,比如poj2352和Codeforces的题目。 首先,我需要解释二维树状数组的基本概念。二维树状数组树状数组二维空间的扩展,主要用于处理二维数组的前缀和查询和单点更新。用户可能已经了解一维树状数组,所以可以在此基础上进行扩展。 接下来是实现部分。用户需要具体的代码示例,尤其是Python的实现。根据引用3,一维树状数组的Python实现,我需要将其扩展到二维二维树状数组的操作包括初始化、单点更新和前缀和查询。需要注意的是,二维情况下,每个更新和查询操作都需要双重循环,遍历每个维度上的索引。 然后是应用场景。用户可能想知道在什么情况下使用二维树状数组。根据引用2和4,二维树状数组适用于子矩阵求和、动态二维网格数据更新等场景,比如处理二维偏序问题或实时更新矩阵中的元素值。例如,在POJ 1195这道题中,需要处理手机的更新和区域查询,这正是二维树状数组的典型应用。 另外,用户可能关心时间复杂度。每个操作的时间复杂度是O((log n)^2),因为每个维度都需要log n的时间。相比暴力方法,这在处理大规模数据时更高效。 最后,生成相关问题。根据用户之前的问题,可能需要关于优化、应用场景以及与其他数据结构的比较的问题。比如,二维树状数组二维线段树的区别,或者如何扩展到更高维度。 需要确保代码正确无误,并符合Python语法。同时,引用相关文献,比如引用2中的二维树状数组应用和引用4中的例题,来增强回答的可信度。还要注意用户的中文回答要求,保持结构清晰,分步骤解释。</think>### 二维树状数组实现与应用详解 #### 一、核心原理 二维树状数组是树状数据结构在二维空间的扩展,主要用于高效处理**子矩阵和查询**和**单点更新**。其核心原理基于二维二进制索引结构: 1. 每个节点存储特定子矩阵的和 2. 通过**lowbit(x)**运算确定覆盖范围 3. 时间复杂度:单次查询/更新 $O((\log n)^2)$ #### 二、Python实现代码 ```python class BinaryIndexedTree2D: def __init__(self, rows, cols): self.n = rows self.m = cols self.tree = [[0]*(cols+1) for _ in range(rows+1)] def update(self, x, y, delta): # 单点更新操作 i = x while i <= self.n: j = y while j <= self.m: self.tree[i][j] += delta j += j & -j i += i & -i def query(self, x, y): # 查询(1,1)到(x,y)的子矩阵和 res = 0 i = x while i > 0: j = y while j > 0: res += self.tree[i][j] j -= j & -j i -= i & -i return res def range_query(self, x1, y1, x2, y2): # 查询任意子矩阵和 return (self.query(x2, y2) - self.query(x1-1, y2) - self.query(x2, y1-1) + self.query(x1-1, y1-1)) ``` #### 三、典型应用场景 1. **动态矩阵求和**:实时更新矩阵元素值并查询子矩阵和 - 例:POJ 1195 Mobile phones[^4] 2. **二维偏序问题**:统计满足 $x_i < x_j$ 且 $y_i < y_j$ 的点对数量 3. **图像处理**:区域像素值统计与更新 4. **游戏地图**:动态更新地形数据并快速统计区域属性 #### 四、操作时间复杂度对比 | 操作类型 | 暴力方法 | 二维树状数组 | |----------------|------------|--------------| | 单点更新 | $O(1)$ | $O((\log n)^2)$ | | 子矩阵查询 | $O(n^2)$ | $O((\log n)^2)$ | | 区域更新+查询 | $O(n^2)$ | $O((\log n)^2)$ | #### 五、实战技巧 1. **坐标偏移**:当坐标从0开始时,统一+1转换为从1开始 2. **离散化处理**:当坐标范围过大时先进行离散化 3. **差分技巧**:处理区间更新操作 ```python # 给子矩阵(x1,y1)-(x2,y2)统一加delta bit.update(x1, y1, delta) bit.update(x1, y2+1, -delta) bit.update(x2+1, y1, -delta) bit.update(x2+1, y2+1, delta) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值