AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

AcWing 243. $\Large\color{blue}{【算法提高课】一个简单的整数问题2(线段树)}$    原题链接    困难

作者: 作者的头像   incra ,  2022-10-02 09:41:02 ,  所有人可见 ,  阅读 1191


13


<—点个赞吧QwQ

宣传一下算法提高课整理{:target=”_blank”}

给定一个长度为 $N$ 的数列 $A$,以及 $M$ 条指令,每条指令可能是以下两种之一:

  1. C l r d,表示把 $A\[l\],A\[l+1\],…,A\[r\]$ 都加上 $d$。
  2. Q l r,表示询问数列中第 $l \\sim r$ 个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数 $N,M$。

第二行 $N$ 个整数 $A\[i\]$。

接下来 $M$ 行表示 $M$ 条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

$1 \\le N,M \\le 10^5$,
$|d| \\le 10000$,
$|A\[i\]| \\le 10^9$

输入样例:

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

输出样例:

4
55
9
15

思路

这道题是非常经典的线段树问题。
不会线段树的请左转线段树详解

代码

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 100010;
int n,m;
int a[N];
struct segment_tree {
    int l,r;
    LL sum,tag;
}tr[N * 4];
void push_up (int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void push_down (int u) {
    auto &root = tr[u],&left = tr[u << 1],&right = tr[u << 1 | 1];
    if (root.tag) {
        left.tag += root.tag,left.sum += (LL)(left.r - left.l + 1) * root.tag;
        right.tag += root.tag,right.sum += (LL)(right.r - right.l + 1) * root.tag;
        root.tag = 0;
    }
}
void build (int u,int l,int r) {
    if (l == r) {
        tr[u] = {l,r,a[l],0};
        return ;
    }
    tr[u] = {l,r};
    int mid = l + r >> 1;
    build (u << 1,l,mid),build (u << 1 | 1,mid + 1,r);
    push_up (u);
}
void modify (int u,int l,int r,int d) {
    if (l <= tr[u].l && tr[u].r <= r) {
        tr[u].sum += (LL)(tr[u].r - tr[u].l + 1) * d;
        tr[u].tag += d;
        return ;
    }
    push_down (u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid) modify (u << 1,l,r,d);
    if (r >= mid + 1) modify (u << 1 | 1,l,r,d);
    push_up (u);
}
LL query_sum (int u,int l,int r) {
    if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum;
    push_down (u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum += query_sum (u << 1,l,r);
    if (r >= mid + 1) sum += query_sum (u << 1 | 1,l,r);
    return sum;
}
int main () {
    scanf ("%d%d",&n,&m);
    for (int i = 1;i <= n;i++) scanf ("%d",&a[i]);
    build (1,1,n);
    while (m--) {
        char op;
        int l,r;
        cin >> op >> l >> r;
        if (op == 'C') {
            int d;
            cin >> d;
            modify (1,l,r,d);
        }
        else printf ("%lld\n",query_sum (1,l,r));
    }
    return 0;
}

4 评论


用户头像
iiiiiiire   2023-05-15 20:26         踩      回复

查询函数 mid取值是不是弄错了

用户头像
incra   2023-05-16 17:17         踩      回复

是的,感谢提醒


用户头像
huangweiliang   2023-01-31 09:09         踩      回复
 OOOO  
O    O r rr zzzz
O    O rr     z
O    O r     z
 OOOO  r    zzzz
用户头像
incra   2023-01-31 09:11      1    踩      回复

qwq


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息