[POJ1195] Mobile phones(二维树状数组)

摘要:
ID=1195有四个操作:0:初始化S*S的零矩阵1:点(x,y)是一个值+A2:查询子矩阵中所有数字的和3:退出段树。由于标记不能在两棵树之间传递,所以这种求和运算非常难处理。我将其更改为树阵列,发现它比二维线段树简单得多。对于这个问题,如果你想查询起点不是(0,0)的子矩阵的和,你需要像一维树数组一样处理重叠部分,如下图所示:这真的很容易写。

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

题意:四种操作:

0:初始化一个S*S的零矩阵

1:点(x,y)是值+A

2:查询一个子矩阵里所有数的和

3:退出

线段树由于不能在两棵树之间传递标记,所以这种求和的操作非常难处理。

改学了一下而为树状数组,发现可是比二维线段树简单多了。

记得之前曾经看过zkw线段树的ppt讲稿,好像zkw线段树的实现方法就是利用下标<<1和<<1|1可以构成一棵树而做的优化,所有对节点的操作跟树状数组极其相似,看来可以放弃普通树套树的二维线段树,而学用zkw线段树了。

这里二维树状数组update操作为从(0,0)到(x,y)这个子矩阵所有的值+val。

sum就是查询(0,0)到(x,y)这个子矩阵所有值的和。

对于本题,想要查询起点非(0,0)的子矩阵的和,只要和一维树状数组一样处理一下重叠部分就可以了,见下图:

[POJ1195] Mobile phones(二维树状数组)第1张

真的是太好写了。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <climits>
 6 #include <complex>
 7 #include <cassert>
 8 #include <cstdio>
 9 #include <bitset>
10 #include <vector>
11 #include <deque>
12 #include <queue>
13 #include <stack>
14 #include <ctime>
15 #include <set>
16 #include <map>
17 #include <cmath>
18 using namespace std;
19 
20 const int maxn = 2020;
21 int n;
22 int bit[maxn][maxn];
23 inline int lowbit(int x) { return x & (-x); }
24 
25 void update(int i, int j, int val) {
26     for(int x = i; x <= n; x += lowbit(x)) {
27         for(int y = j; y <= n; y += lowbit(y)) {
28             bit[x][y] += val;
29         }
30     }
31 }
32 
33 int sum(int i, int j) {
34     int ret = 0;
35     for(int x = i; x > 0; x -= lowbit(x)) {
36         for(int y = j; y > 0; y -= lowbit(y)) {
37             ret += bit[x][y];
38         }
39     }
40     return ret;
41 }
42 
43 int main() {
44     // freopen("in", "r", stdin);
45     int op;
46     int x1, y1, x2, y2, val;
47     scanf("%d%d",&op,&n);
48     memset(bit, 0, sizeof(bit));
49     while(~scanf("%d", &op) && op != 3) {
50         if(op == 1) {
51             scanf("%d%d%d",&x1,&y1,&val);
52             x1++; y1++;
53             update(x1, y1, val);
54         }
55         else {
56             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
57             x1++; y1++; x2++; y2++;
58             int a = sum(x1-1, y1-1);
59             int b = sum(x2, y1-1);
60             int c = sum(x1-1, y2);
61             int d = sum(x2, y2);
62             printf("%d
", a + d - c - b);
63         }
64     }
65 }

顺便祭奠一下写挂了的二维线段树:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define lrt rt << 1
 5 #define rrt rt << 1 | 1
 6 const int maxn = 1030;
 7 
 8 
 9 typedef struct NodeY {
10     int val;
11 }NodeY;
12 
13 typedef struct NodeX {
14     NodeY segY[maxn<<2];
15     void build(int l, int r, int rt) {
16         segY[rt].val = 0;
17         if(l == r) return;
18         int mid = (l + r) >> 1;
19         build(l, mid, lrt);
20         build(mid+1, r, rrt);
21     }
22 
23     void pushup(int rt) {
24         segY[rt].val = segY[lrt].val + segY[rrt].val;
25     }
26 
27     void update(int p, int val, int l, int r, int rt) {
28         if(l == r) {
29             segY[rt].val += val;
30             return;
31         }
32         int mid = (l + r) >> 1;
33         if(p <= mid) update(p, val, l, mid, lrt);
34         else update(p, val, mid+1, r, rrt);
35         pushup(rt);
36     }
37 
38     int query(int L, int R, int l, int r, int rt) {
39         if(L <= l && r <= R) return segY[rt].val;
40         int mid = (l + r) >> 1;
41         int ret = 0;
42         if(L <= mid) ret += query(L, R, l, mid, lrt);
43         if(mid < R) ret += query(L, R, mid+1, r, rrt);
44         return ret;
45     }
46 }NodeX;
47 
48 NodeX segX[maxn<<2];
49 int n;
50 
51 void build(int l, int r, int rt) {
52     segX[rt].build(1, n, 1);
53     if(l == r) return;
54     int mid = (l + r) >> 1;
55     build(l, mid, lrt);
56     build(mid+1, r, rrt);
57 }
58 
59 void update(int x, int y, int val, int l, int r, int rt) {
60     segX[rt].update(y, val, 1, n, 1);
61     if(l == r) return;
62     int mid = (l + r) >> 1;
63     if(x <= mid) update(x, y, val, l, mid, lrt);
64     else update(x, y, val, mid+1, r, rrt);
65 }
66 
67 int query(int y1, int y2, int L, int R, int l, int r, int rt) {
68     if(L <= l && r <= R) return segX[rt].query(y1, y2, 1, n, 1);
69     int mid = (l + r) >> 1;
70     int ret = 0;
71     if(L <= mid) ret += query(y1, y2, L, R, l, mid, lrt);
72     if(mid < R) ret += query(y1, y2, L, R, mid+1, r, rrt);
73     return ret;
74 }
75 
76 int main() {
77     freopen("in", "r", stdin);
78     int op, a, b, c, d;
79     scanf("%d %d", &op, &n);
80     build(1, n, 1);
81     while(~scanf("%d", &op) && op != 3) {
82         if(op == 1) {
83             scanf("%d%d%d",&a,&b,&c);
84             cout << a << " " << b << endl;
85             a++; b++;
86             update(a, b, c, 1, n, 1);
87         }
88         if(op == 2) {
89             scanf("%d%d%d%d",&a,&b,&c,&d);
90             a++; b++; c++; d++;
91             printf("%d
", query(c, d, a, b, 1, n, 1));
92         }
93     }
94     return 0;
95 }

免责声明:文章转载自《[POJ1195] Mobile phones(二维树状数组)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇COGNOS主要产品比较HTTP请求时connectionRequestTimeout 、connectionTimeout、socketTimeout三个超时时间的含义下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Lua中table的实现-《Lua设计与实现》

本文来自《Lua设计与实现》的阅读笔记,推荐Lua学习者可以购买一本,深入浅出讲解lua的设计和实现原理,很赞,哈哈   Lua中对于表的设计,是基于数组和散列表,和其他语言不同,对于数组的下标是从1开始的,对于散列表而言,只要其键值补位nil,都可以存储在其中。   一、table的基本类型定义 首先看看table的数据定义,参考源码lobject.h...

svn的应用

SVN 如何来进行多人协作开发? 在实际工作中,通常是一个小组或者一个团队一起开发同一个项目,不同的人开发不同的功能模块,有一个公共的地方存放项目代码。 如果多个人同时对同一个文件做了修改,比如按照分工,两个人分别做文章模块的增删改查功能,需要操作同一个文件article控制器,如果大家同时完成工作并提交代码,会出现一个代码覆盖的问题。 解决办法: ①合理...

【Python之路】特别篇--ECMA对象、DOM对象、BOM对象

ECMA对象从传统意义上来说,ECMAScript 并不真正具有类。事实上,除了说明不存在类,在 ECMA-262 中根本没有出现“类”这个词。 ECMAScript 定义了“对象定义”,逻辑上等价于其他程序设计语言中的类。 var o = new Object(); 对象的概念与分类: 由ECMAScript定义的本地对象.独立于宿主环境的 ECMAS...

将一个文件夹中我们需要的文件拷贝到另一个文件夹中的代码实现

1 package cn.itsource.homework; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.util.ArrayList; 7 /** 8 * 需求:...

【转】 PostgreSQL数据类型

第六章数据类型 6.1概述 PostgreSQL提供了丰富的数据类型。用户可以使用CREATE TYPE命令在数据库中创建新的数据类型。PostgreSQL的数据类型被分为四种,分别是基本数据类型、复合数据类型、域和伪类型。 基本数据类型是数据库内置的数据类型,包括integer、char、varchar等数据类型。表6-1列出了PostgreSQL提供的...

使用java8的stream对数组进行求和

1、对BigDecimal类型的值求和。 List<Map<String,Object>> list = new ArrayList<>(); Map<String,Object> stu1 = new HashMap<String, Object>(); stu1.put("name", "张三...