洛谷 P3372 【模板】线段树 1

洛谷 P3372 【模板】线段树 1

传送门

思路

前几天学了线段树的我,今天又去做了一遍线段树【模板】\(1\),发现自己打代码真的是漏洞百出啊,不过最后还是对了,所以来水一篇博客

首先,这道模板题的要求就是:

1.区间加
2.区间求和

这两个操作都属于线段树的基本操作

前置——宏定义

#define N 100011
#define lson rt << 1
#define rson rt << 1 | 1
#define int long long

由于我特别懒,不想写什么\(rt << 1\)之类的东西,所以直接宏定义就好了,还有,为了不改\(int\),我直接把\(int\)宏定义为\(long \ long\),省的麻烦(我真的是懒到家了)

1.定义

int sum[N << 2], lazy[N << 2], n, m;

众所周知,线段树一般要开四倍空间,不明白的可以自己画一颗线段树数一下,sum数组维护区间和,lazy是懒标记

2.pushup

inline void pushup(int rt) {
    sum[rt] = sum[lson] + sum[rson];
}

这是一个上传给父亲结点的信息的函数,当前节点的区间和就等于它左儿子和右儿子的区间和之和

2.建树

void build(int l, int r, int rt) {
    if(l == r) {
        sum[rt] = read();
        return;
    }
    int m = (l + r) >> 1;
    build(l, m, lson);
    build(m + 1, r, rson);
    pushup(rt);
}

上面是建树过程,\(rt\)表示当前节点,\(lson\)是左孩子,\(rson\) 是右孩子

3.标记下放

inline void pushdown(int l, int r, int rt) {
    if(!lazy[rt]) return;
    lazy[lson] += lazy[rt];
    lazy[rson] += lazy[rt];
    int m = (l + r) >> 1;
    sum[lson] += (m - l + 1) * lazy[rt];
    sum[rson] += (r - m) * lazy[rt];
    lazy[rt] = 0;
    return;
}

pushdown函数的实现:
1.用lazy存储这个懒标记。
2.递归到这个节点时,只更新这个节点的状态,并把当前的更改值累积到标记中。
什么时候才用到这个懒标记?
当需要递归这个节点的子节点时,标记下传给子节点。
3.下放操作:(三步)
当前节点的懒标记累积到子节点的懒标记中。
修改子节点状态。
父节点懒标记清0。

4.区间修改

void update(int L, int R, int c, int l, int r, int rt) {
    if(L <= l && r <= R) {
        sum[rt] += c * (r - l + 1);
        lazy[rt] += c;
        return;
    }
    pushdown(l, r, rt);
    int m = (l + r) >> 1;
    if(L <= m) update(L, R, c, l, m, lson);
    if(R > m) update(L, R, c, m + 1, r, rson);
    pushup(rt);
}

5.区间求和

int query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) return sum[rt];
    pushdown(l, r, rt);
    int m = (l + r) >> 1, ans = 0;
    if(L <= m) ans += query(L, R, l, m, lson);
    if(R > m) ans += query(L, R, m + 1, r, rson);
    return ans;
}

代码

下面上传高清无码无水印代码

#include <bits/stdc++.h>
#define N 100011
#define lson rt << 1
#define rson rt << 1 | 1
#define int long long
using namespace std;

int sum[N << 2], lazy[N << 2], n, m;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

inline void pushup(int rt) {
    sum[rt] = sum[lson] + sum[rson];
}

void build(int l, int r, int rt) {
    if(l == r) {
        sum[rt] = read();
        return;
    }
    int m = (l + r) >> 1;
    build(l, m, lson);
    build(m + 1, r, rson);
    pushup(rt);
}

inline void pushdown(int l, int r, int rt) {
    if(!lazy[rt]) return;
    lazy[lson] += lazy[rt];
    lazy[rson] += lazy[rt];
    int m = (l + r) >> 1;
    sum[lson] += (m - l + 1) * lazy[rt];
    sum[rson] += (r - m) * lazy[rt];
    lazy[rt] = 0;
    return;
}

void update(int L, int R, int c, int l, int r, int rt) {
    if(L <= l && r <= R) {
        sum[rt] += c * (r - l + 1);
        lazy[rt] += c;
        return;
    }
    pushdown(l, r, rt);
    int m = (l + r) >> 1;
    if(L <= m) update(L, R, c, l, m, lson);
    if(R > m) update(L, R, c, m + 1, r, rson);
    pushup(rt);
}

int query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) return sum[rt];
    pushdown(l, r, rt);
    int m = (l + r) >> 1, ans = 0;
    if(L <= m) ans += query(L, R, l, m, lson);
    if(R > m) ans += query(L, R, m + 1, r, rson);
    return ans;
}

signed main() {
    n = read(), m = read();
    build(1, n, 1);
    for(int i = 1; i <= m; i++) {
        int opt = read(), x = read(), y = read();
        if(opt == 1) {
            int k = read();
            update(x, y, k, 1, n, 1);
        }
        if(opt == 2) cout << query(x, y, 1, n, 1) << '\n';
    }
    return 0;
}

转载于:https://www.cnblogs.com/loceaner/p/11122049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值