zoukankan      html  css  js  c++  java
  • 线段树模板1 [Luogu P3372]

    代码+注释:

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 
     5 int n, q, flag, x, y, v;
     6 int a[100010];
     7 struct node{
     8     long long a, b;
     9 }tree[400010];    //树,a为数据域,b为标记
    10 
    11 void build_tree(int now, int l, int r) {    //建树
    12     if (l == r) {
    13         tree[now].a = a[l];            //填充数据
    14         return ;
    15     }
    16     int mid = (l + r) >> 1;            //mid = (l + r) div 2; 位运算加速
    17     build_tree(now + now, l, mid);        //往左边继续建树
    18     build_tree(now + now + 1, mid + 1, r);    //往右边继续建树
    19     tree[now].a = tree[now + now].a + tree[now + now + 1].a;    //此时节点数据域为下接两个节点的和,便于查询
    20 }
    21 
    22 void plust(int now, int l, int r, int x, int y) {//区间加操作
    23     if ((l == x) && (r == y) || (l == r)) {    //达到要求
    24         tree[now].a += v * (r - l + 1);        //累加v的值与当前节点下所有的节点数的积(若当前节点下没有节点则为1)
    25         tree[now].b += v;            //打标记
    26         return ;                //回溯
    27     }
    28     int mid = (l + r) >> 1;
    29     tree[now + now].b += tree[now].b;        //向下传递标记(以下都是)
    30     tree[now + now + 1].b += tree[now].b;
    31     tree[now + now].a += (tree[now].b * (mid - l + 1));
    32     tree[now + now + 1].a += (tree[now].b * (r - mid));
    33     tree[now].b = 0;                //向下传递标记,当前标记清空(不管怎么样就是这样)
    34     if (y <= mid) plust(now + now, l, mid, x, y);//若操作区间在mid左边,往左边继续操作
    35     else if (x > mid) plust(now + now + 1, mid + 1, r, x, y);//若在mid右边,往右边继续操作
    36     else {                    //否则拆开分别左右操作
    37         plust(now + now, l, mid, x, mid);
    38         plust(now + now + 1, mid + 1, r, mid + 1, y);
    39     }
    40     tree[now].a = tree[now + now].a + tree[now + now + 1].a; //更新当前节点的数据
    41 }
    42 
    43 long long query(int now, int l, int r, int x, int y) {    //区间查询
    44     if ((l == x) && (r == y)) return tree[now].a;    //若当前节点所代表的区间恰好与需要查询的区间重合,返回值
    45     int mid = (l + r) >> 1;
    46     tree[now + now].b += tree[now].b;        //同上,向下传递标记(以下都是)
    47     tree[now + now + 1].b += tree[now].b;
    48     tree[now + now].a += (tree[now].b * (mid - l + 1));
    49     tree[now + now + 1].a += (tree[now].b * (r - mid));
    50     tree[now].b = 0;                //同上,向下传递标记
    51     if (y <= mid) return query(now + now, l, mid, x, y);    //查询区间在mid左边,往左边取
    52     else if (x > mid) return query(now + now + 1, mid + 1, r, x, y);    //否则在右边取
    53     else return query(now + now, l, mid, x, mid) + query(now + now + 1, mid + 1, r, mid + 1, y); //再否则断开从左右边取
    54 }
    55 
    56 int main() {                //主程序
    57     scanf("%d%d", &n, &q);        //读入数列的长度和操作的次数
    58     for (int i = 1; i <= n; i++)
    59         scanf("%d", &a[i]);
    60 
    61     build_tree(1, 1, n);        //建树
    62     
    63     for (int i = 1; i <= q; i++) {
    64         scanf("%d%d%d", &flag, &x, &y);    //开始
    65         if (flag == 1) {
    66             scanf("%d", &v);        //v为要加进去的数
    67             plust(1, 1, n, x, y);    //区间加操作
    68             continue;
    69         }
    70         printf("%lld
    ", query(1, 1, n, x, y));  //否则查询区间
    71     }
    72     
    73     return 0;
    74 }

    供个人复习使用

  • 相关阅读:
    Hibernate 查询,返回结果设置到DTO
    sqlserver计算时间差DATEDIFF 函数
    SQL语句 不足位数补0
    Redis详细用法
    windows下安装Redis并部署成服务
    Redis命令
    ajax请求在参数中添加时间戳
    JS获取子节点、父节点和兄弟节点的方法实例总结
    js关闭当前页面清除session
    Java面试题一览
  • 原文地址:https://www.cnblogs.com/SJum/p/8544066.html
Copyright © 2011-2022 走看看