• 线段树区间修改


    这里给一个区间修改,求区间和的代码,也可以用到求区间最值,乘积等问题。 

    这个想法是sum[]和lazy[]同时修改。以前我写的是lazy[now]往下传给now << 1和now << 1 | 1的时候再修改sum[],这个写法的逻辑不是很好,推荐下面的这个思路。

     1 #include<cstdio>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e5 + 5;
     5 
     6 int l[maxn << 2], r[maxn << 2], lazy[maxn << 2];
     7 ll sum[maxn << 2];
     8 void build(int L, int R, int now)
     9 {
    10     l[now] = L; r[now] = R;
    11     if(L == R) {scanf("%lld", &sum[now]); return;}
    12     int mid = (L + R) >> 1;
    13     build(L, mid, now << 1);
    14     build(mid + 1, R, now << 1 | 1);
    15     sum[now] = sum[now << 1] + sum[now << 1 | 1];
    16 }
    17 void pushdown(int now)
    18 {
    19     if(lazy[now])
    20     {
    21         lazy[now << 1] += lazy[now];
    22         lazy[now << 1 | 1] += lazy[now];
    23         sum[now << 1] += (r[now << 1] - l[now << 1] + 1) * lazy[now];
    24         sum[now << 1 | 1] += (r[now << 1 | 1] - l[now << 1 | 1] + 1) * lazy[now];
    25         lazy[now] = 0;
    26     }
    27 }
    28 void update(int L, int R, int now, int d)
    29 {
    30     if(L == l[now] && R == r[now])
    31     {
    32         sum[now] += (r[now] - l[now] + 1) * d;
    33         lazy[now] += d;
    34         return;
    35     }
    36     pushdown(now);    
    37     int mid = (l[now] + r[now]) >> 1;
    38     if(R <= mid) update(L, R, now << 1, d);
    39     else if(L > mid) update(L, R, now << 1 | 1, d);
    40     else {update(L, mid, now << 1, d); update(mid + 1, R, now << 1 | 1, d);}
    41     sum[now] = sum[now << 1] + sum[now << 1 | 1];
    42 }
    43 ll query(int L, int R, int now)
    44 {
    45     if(L == l[now] && R == r[now]) return sum[now];
    46     pushdown(now);
    47     int mid = (l[now] + r[now]) >> 1;
    48     if(R <= mid) return query(L, R, now << 1);
    49     else if(L > mid) return query(L, R, now << 1 | 1);
    50     else return query(L, mid, now << 1) + query(mid + 1, R, now << 1 | 1);
    51 }
    52 
    53 int main()
    54 {
    55     int n, m; scanf("%d%d", &n, &m);
    56     build(1, n, 1);
    57     for(int i = 1; i <= m; ++i)
    58     {
    59         int d; scanf("%d", &d);
    60         if(d == 1) 
    61         {
    62             int a, b, c; scanf("%d%d%d", &a, &b, &c);
    63             update(a, b, 1, c); 
    64         }
    65         else
    66         {
    67             int a, b; scanf("%d%d", &a, &b);
    68             printf("%lld
    ", query(a, b, 1));
    69         }
    70     }
    71 }
  • 相关阅读:
    OAuth2 协议原理简析及Azure AD OAuth2示例
    MySQL Innodb MVCC(多版本并发控制)
    乐观锁和悲观锁
    数据库索引
    SQL盲注
    JAVA array to list and list to array
    缓存穿透,缓存雪崩和缓存击穿
    四、Spring Cloud 之旅 -- Ribbon 负载均衡
    JavaScript中 require、import 有什么区别?
    vue 2.x Vue 3.x 日常采坑之 设置alias别名、background引入图片、全局引入scss文件 的问题
  • 原文地址:https://www.cnblogs.com/mrclr/p/9028134.html
Copyright © 2020-2023  润新知