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

题目链接: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)的子矩阵的和,只要和一维树状数组一样处理一下重叠部分就可以了,见下图:

 

真的是太好写了。

 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\n", 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\n", query(c, d, a, b, 1, n, 1));
92         }
93     }
94     return 0;
95 }

 

posted @ 2017-05-02 21:00  Kirai  阅读(233)  评论(0编辑  收藏  举报