• 树状数组--模版1和2 P3368、P3374


    题目描述
    如题,已知一个数列,你需要进行下面两种操作:
    
    将某一个数加上 x
    
    求出某区间每一个数的和
    
    输入格式
    第一行包含两个正整数 n,m,分别表示该数列数字的个数和操作的总个数。
    
    第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i项的初始值。
    
    接下来 m 行每行包含 3 个整数,表示一个操作,具体如下:
    
    1 x k 含义:将第 x 个数加上 k
    
    2 x y 含义:输出区间 [x,y]内每个数的和
    
    输出格式
    输出包含若干行整数,即为所有操作 2 的结果。
    令这棵树的结点编号为C1,C2...Cn。令每个结点的值为这棵树的值的总和,那么容易发现:
    C1 = A1
    C2 = A1 + A2
    C3 = A3
    C4 = A1 + A2 + A3 + A4
    C5 = A5
    C6 = A5 + A6
    C7 = A7
    C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
    ...
    C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
    这里有一个有趣的性质:
    设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,
    所以很明显:Cn = A(n – 2^k + 1) + ... + An

     

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 int n,m;
     5 int x,y;
     6 int w1;
     7 int a[500001];
     8 int s[500001];
     9 void fix(int x,int v)
    10 {
    11     for (int i = x;i <= n;i+=i&-i)
    12     {
    13         s[i]+=v;
    14     }
    15 }
    16 int find(int x)
    17 {
    18     int ret=0;
    19     for (int i = x;i>0;i-=i&-i)
    20     {
    21         ret+=s[i];
    22     
    23     }    
    24     return ret;
    25 }
    26 int main()
    27 {
    28     scanf ("%d%d",&n,&m);
    29     for (int i = 1;i <= n;i++)
    30     {
    31         scanf ("%d",&a[i]);
    32         fix(i,a[i]);
    33     }
    34     for (int i = 1;i <= m;i++)
    35     {
    36         scanf ("%d",&w1);scanf ("%d%d",&x,&y);
    37         if (w1==1){
    38             fix(x,y);
    39         }
    40         if (w1==2)
    41         {
    42             cout<<find(y)-find(x-1)<<endl;
    43         }
    44     }
    45     return 0;
    46 }

     

     2.模版2

    题目描述

    如题,已知一个数列,你需要进行下面两种操作:

    1.将某区间每一个数数加上x

    2.求出某一个数的值

    输入格式

    第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

    第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

    接下来M行每行包含2或4个整数,表示一个操作,具体如下:

    操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k

    操作2: 格式:2 x 含义:输出第x个数的值

    输出格式

    输出包含若干行整数,即为所有操作2的结果。

    因为本题不是单纯修改一个数,而是修改一段区间的数,所以fix(x,k)表示把x到最后一个数都加上,但是我们把y+1到最后一个数也都加上了k,而我们只需要把x到y加k,所以fix(y+1,-k)把y+1到最后一个数都减去k,就是把多加的都减去。我们就知道了每个数所对应的修改量,把原来的数加上修改量,就是所得的数

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 long long n,m;
     5 long long x,y,k;
     6 long long w1;
     7 long long a[500001];
     8 long long s[500001];
     9 void fix(long long x,long long v)
    10 {
    11     for (long long i = x;i <= n;i+=i&-i)
    12     {
    13         s[i]+=v;
    14     }
    15 }
    16 long long find(long long x)
    17 {
    18     long long ret=0;
    19     for (long long i = x;i>0;i-=i&-i)
    20     {
    21         ret+=s[i];
    22     }    
    23     return ret;
    24 }
    25 int main()
    26 {
    27     scanf ("%lld%lld",&n,&m);
    28     for (int i = 1;i <= n;i++)
    29     {
    30         scanf ("%lld",&a[i]);
    31     }
    32     for (int i = 1;i <= m;i++)
    33     {
    34         scanf ("%lld",&w1);
    35         if (w1==1){
    36             scanf ("%lld%lld%lld",&x,&y,&k);
    37             fix(x,k);
    38             fix(y+1,-k);
    39         }
    40         if (w1==2)
    41         {
    42             scanf ("%lld",&x);
    43             cout<<a[x]+find(x)<<endl;
    44         }
    45     }
    46     return 0;
    47 }

     

  • 相关阅读:
    python3.6+requests实现接口自动化4
    python3.6+requests实现接口自动化3
    Druid学习之路 (五)Druid的数据摄取任务类型
    Druid学习之路 (四)Druid的数据采集格式
    Druid学习之路 (三)Druid的数据源和段
    Druid学习之路 (二)Druid架构
    Druid学习之路 (一)Druid初识
    Hive sql和Presto sql的一些对比
    Pyspark的HBaseConverters详解
    Pyspark访问Hbase
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12199592.html
Copyright © 2020-2023  润新知