zoukankan      html  css  js  c++  java
  • [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
    ", 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 }
  • 相关阅读:
    Silverlight应用小知识点
    svn如何给新文件加锁
    sql统计上周销售量的起止时间
    sql中null 和 ‘’(空字符串)
    蓝桥杯 算法训练 操作格子 [ 线段树 ]
    90分 蓝桥杯 算法提高 道路和航路 [ 最短路 ]
    蓝桥杯 算法训练 安慰奶牛 [ 最小生成树 ]
    蓝桥杯 算法提高 金属采集 [ 树形dp 经典 ]
    转 蓝桥杯 历届试题 大臣的旅费 [ dfs 树的直径 ]
    蓝桥杯 算法训练 最短路 [ 最短路 bellman ]
  • 原文地址:https://www.cnblogs.com/kirai/p/6798425.html
Copyright © 2011-2022 走看看