zoukankan      html  css  js  c++  java
  • 洛谷P3372--线段树代码模板1

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

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

    2.求出某区间每一个数的和

    输入格式

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

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

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

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

    操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

    输出格式

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

    输入输出样例

    输入 #1
    5 5
    1 5 4 2 3
    2 2 4
    1 2 3 2
    2 3 4
    1 1 5 1
    2 1 4
    输出 #1
    11
    8
    20

    说明/提示

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=8,M<=10

    对于70%的数据:N<=1000,M<=10000

    对于100%的数据:N<=100000,M<=100000

    (数据已经过加强^_^,保证在int64/long long数据范围内)

    样例说明:

      1 #include<iostream>
      2 #include<stdio.h>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<vector>
      6 #include<stack>
      7 #include<map>
      8 #include<set>
      9 #include<list>
     10 #include<queue>
     11 #include<string>
     12 #include<algorithm>
     13 #include<iomanip>
     14 using namespace std;
     15 const int maxn = 100010;
     16 int arr[maxn +5];
     17 struct node
     18 {
     19     /* data */
     20     long long  value;//该结点维护的值
     21     int left;
     22     int right;
     23     long long add;//lazy 每个区间的增量
     24 }tree[maxn* 4 + 5];
     25 
     26 
     27 inline void PushUp(int root)
     28 {
     29     tree[root].value = tree[root <<1].value + tree[root<<1|1].value;
     30 }
     31 
     32 void Build(int root,int x,int y)
     33 {
     34     tree[root].left = x;
     35     tree[root].right = y;
     36     if(x == y)
     37     {
     38         tree[root].value = arr[x];
     39         return ;
     40     }
     41     int mid = (x + y) >> 1;
     42     Build(root<<1,      x,mid);
     43     Build(root<<1|1,mid+1,y);
     44     PushUp(root);
     45 }
     46 
     47 void Spread(int root)//懒标记
     48 {
     49     if(tree[root].add)//如果树根结点的懒标记不为0 ,修改左右儿子的值
     50     {
     51         tree[root<<1].value   += tree[root].add * (tree[root<<1].right   - tree[root<<1].left   +1);
     52         tree[root<<1|1].value += tree[root].add * (tree[root<<1|1].right - tree[root<<1|1].left +1);
     53         //左右儿子的值增加为父亲结点的增量乘以自己各区间的长度
     54         tree[root<<1].add   += tree[root].add;
     55         tree[root<<1|1].add += tree[root].add;
     56         tree[root].add = 0;//父亲结点增量变为0;
     57     }
     58 }
     59 void Change(int root,int x,int y,int z)//给根结点为root 区间为(x,y)的每个值加上z
     60 {
     61     if( x <= tree[root].left && y  >= tree[root].right)//区间被完全覆盖
     62     {
     63         tree[root].value += (long long )z * (tree[root].right - tree[root].left + 1);
     64         tree[root].add   += z;
     65         return ;
     66     }
     67     Spread(root);//如果没有发现区间被覆盖,即需要继续向下找,并把懒标记下放
     68     int mid = (tree[root].right + tree[root].left) >> 1;
     69     if( x <= mid)//要修还区间覆盖了左儿子,修改
     70     {   
     71         Change(root<<1,x,y,z);
     72     }
     73     if( y > mid)//右儿子同理
     74     {
     75         Change(root<<1|1,x,y,z);
     76     }
     77     PushUp(root);
     78 }
     79 
     80 long long Query(int root,int x,int y)//对区间(x,y)的查询操作
     81 {
     82     long long ans = 0;
     83     if( x <= tree[root].left && y >= tree[root].right )//查询区间被根结点所对应区间覆盖
     84     {
     85         return tree[root].value;
     86     }
     87     Spread(root);//下传懒标记
     88     int mid = (tree[root].left + tree[root].right) >> 1;
     89     if ( x <= mid)
     90     {
     91         ans += Query(root<<1,x,y);
     92     }
     93     if( y > mid)
     94     {
     95         ans += Query(root<<1|1,x,y);
     96     }
     97     return ans;
     98 }
     99 
    100 int main()
    101 {
    102     int n,m;
    103     scanf("%d%d",&n,&m);
    104         for(int i = 1; i<= n;i++)
    105         {
    106             scanf("%d",&arr[i]);
    107         }
    108         Build(1,1,n);
    109         for(int i = 0 ;i < m;i++)
    110         {
    111             int flag;
    112             int x,y,k;
    113             cin>>flag;
    114             if(flag == 1)
    115             {
    116                 scanf("%d%d%d",&x,&y,&k);
    117                 Change(1,x,y,k);
    118             }
    119             else
    120             {
    121                 scanf("%d%d",&x,&y);
    122                 cout<<Query(1,x,y)<<endl;
    123             }
    124         }
    125     return 0;
    126 }
  • 相关阅读:
    20160205
    20151120
    20151023
    20151023
    20140207
    yum工具介绍
    Linux程序包管理
    Linux任务计划、周期性任务执行
    10 压缩和解压缩工具和bash脚本编程
    9 btrfs文件系统
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11279732.html
Copyright © 2011-2022 走看看