zoukankan      html  css  js  c++  java
  • poj 1195:Mobile phones(二维树状数组,矩阵求和)

    Mobile phones
    Time Limit: 5000MS   Memory Limit: 65536K
    Total Submissions: 14489   Accepted: 6735

    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

     
      二维树状数组,经典题
      这道题用二维线段树做也可以,做法见右方链接poj 1195:Mobile phones(二维线段树,矩阵求和)
      二维树状数组和二维线段树效率对比(上为树状数组,下为线段树):
     
      题意
      一个矩阵,初始化为全0。有以下操作:
      1)将 (x,y) 元素加 a。x为行坐标,y为列坐标。
      2)求矩阵 [X,Y] 所有元素的和。该矩阵左上角为[l,b],右下角为[r,t]。
     
      思路
      同一维的树状数组求法差不多。
      分别说明二维树状数组加数和求和的做法:
      1)加数:在矩阵的某个坐标处加上某个数,则二维树状数组中的值也要改变。那么改变哪些位置的值呢?我们知道,一维的加数是不断改变在这个位置之上的所有位置的值,之上的位置是用lowbit()求出来的。例如要改变的位置是x,你要加的数是a,则需要把x不断加上lowbit(),在新的x的位置加上a,然后再将x加lowbit(),再在x上加a……直到x超过这个数组规定的大小。
      二维的也是类似,只不过在计算每一个x的时候,需要再计算一个y。例如要在(x,y)位置加上一个数a。先保持x不变,y不断加lowbit(),在对应的(x,y)的位置加a,直到y超过限界(如果矩阵是4*4的,则这个限界就是4,y<=4)。一轮过后,将x加lowbit(),y恢复一开始的值,再进行新的一轮,这样一轮一轮的直到x也超过限界(同样如果矩阵大小为4*4,则x<=4)。
      如此这般,假设矩阵大小为4*4,则Add的代码如下:
     1 void Add(int x,int y,int a)
     2 {
     3     int i=x;
     4     while(i<=s){
     5         int j=y;
     6         while(j<=s){
     7             c[i][j]+=a;
     8             j+=lowbit(j);
     9         }
    10         i+=lowbit(i);
    11     }
    12 }

      2)求和:对左上角为(l,r),右下角为(b,t)的矩阵求和,即求该矩阵中所有元素的和。先求l到r的行矩阵的和,在求这个行矩阵和的时候,每一行要计算对应的b到t列的元素和。具体过程类似上述过程,将+lowbit()改为-lowbit()即可。限界为>=1。

      

      代码

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 using namespace std;
     5 
     6 #define MAXN 1100
     7 
     8 int c[MAXN][MAXN],s;
     9 
    10 int lowbit(int x)
    11 {
    12     return x&-x;
    13 }
    14 
    15 void Add(int x,int y,int a)    //加数
    16 {
    17     int i=x;
    18     while(i<=s){    //
    19         int j=y;
    20         while(j<=s){    //
    21             c[i][j]+=a;
    22             j+=lowbit(j);
    23         }
    24         i+=lowbit(i);
    25     }
    26 }
    27 
    28 int Sum(int l,int r,int b,int t)    //求和
    29 {
    30     l--,b--;
    31     int suml=0,sumr=0;
    32     //求行矩阵和,l以上矩阵
    33     while(l>=1){
    34         int i=b,j=t;
    35         int sumb=0,sumt=0;
    36         //求列矩阵和
    37         while(i>=1){
    38             sumb+=c[l][i];
    39             i-=lowbit(i);
    40         }
    41         while(j>=1){
    42             sumt+=c[l][j];
    43             j-=lowbit(j);
    44         }
    45         suml+=sumt-sumb;
    46         l-=lowbit(l);
    47     }
    48     //求行矩阵和,r以上矩阵
    49     while(r>=1){
    50         int i=b,j=t;
    51         int sumb=0,sumt=0;
    52         //求列矩阵和
    53         while(i>=1){
    54             sumb+=c[r][i];
    55             i-=lowbit(i);
    56         }
    57         while(j>=1){
    58             sumt+=c[r][j];
    59             j-=lowbit(j);
    60         }
    61         sumr+=sumt-sumb;
    62         r-=lowbit(r);
    63     }
    64     return sumr-suml;
    65 }
    66 
    67 int main()
    68 {
    69     int cmd,x,y,a,l,r,b,t;
    70 
    71     while(scanf("%d",&cmd)!=EOF){
    72         switch(cmd){
    73         case 0:    //初始化矩阵
    74             scanf("%d",&s);
    75             memset(c,0,sizeof(c));
    76             break;
    77 
    78         case 1:    //加数
    79             scanf("%d%d%d",&x,&y,&a);
    80             Add(x+1,y+1,a);
    81             break;
    82 
    83         case 2:    //求矩阵和
    84             scanf("%d%d%d%d",&l,&b,&r,&t);
    85             printf("%d
    ",Sum(l+1,r+1,b+1,t+1));
    86             break;
    87 
    88         case 3:    //退出程序
    89             return 0;
    90         default:
    91             break;
    92         }
    93     }
    94     return 0;
    95 }

    Freecode : www.cnblogs.com/yym2013

  • 相关阅读:
    P1135 奇怪的电梯题解
    P1443 马的遍历题解
    P2392 kkksc03考前临时抱佛脚题解
    P1219 八皇后问题题解
    IDEA导入/导出live templates或者其他设置
    P3743 kotori的设备题解
    带你看论文丨全局信息对于图网络文档解析的影响
    【“互联网+”大赛华为云赛道】EI命题攻略:华为云EI的能力超丰富,助你实现AI梦想
    【“互联网+”大赛华为云赛道】IoT命题攻略:仅需四步,轻松实现场景智能化设计
    只需6步,教你从零开发一个签到小程序
  • 原文地址:https://www.cnblogs.com/yym2013/p/3872542.html
Copyright © 2011-2022 走看看