问题描述:

已知一个数列,对数列进行两种操作:1,对数列某个区间中的所有数加d;2,查询数列某区间的区间和

输入:

第一行输入两个整数n和m,分别代表数列中元素个数和对数列的操作次数,第二行输入n个用空格隔开的整数,接下来的m行输入3或4个整数,表示m种操作:

(1)1 L R d:表示对区间[L,R]中的所有数字加d;

(2)2 L R:表示查询并输出[L,R]区间的区间和;

输出:

输出所有操作2的区间和

数据范围:

1<=m,n<=10e5, 数列中元素取值为[-2e63,2e63];

线段树:

使用线段树首先要明确树状数组的叶子节点和子树根节点代表什么,叶子节点自然是代表数组中的元素,由于本题需要解决的都是有关区间的问题,所以子树根节点自然就是区间和,但本题还涉及到区间修改,如果直接再区间中修改,那么每次修改都需要从该修改区间向下传递修改信息直到叶子节点,但查询操作并不是每次修改后都需要查询,显然这将会进行很多不必要的操作增加时间复杂度,有什么可以一劳永逸的呢,最简单直观的方法就是先不修改,直到读取到查询操作的时候再将修改信息传递,对,这就是离线操作和在线操作的区别,也就是线段树中常用的lazy_tag操作,接下来直接看代码:

#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
ll a[N]; //记录数列元素
ll tree[N << 2]; //线段树
ll tag[N << 2];
ll ls(ll p) { return p << 2; }
ll rs(ll p) { return p << 2 | 1; } void pushup(ll p) {
tree[p] = tree[ls(p)] + tree[rs(p)];
} //建立线段树
void build(ll p, ll pl, ll pr) {
//调用build(1,1,n);
tag[p] = 0; //由于线段树结构的特性,数组中有很多空位置,我们不去使用那些空位,只更新线段树用到的位置
if (pl == pr) {
tree[p] = a[pl]; return; //此时p=pl=pr,不明白的可以看看线段树的图解
}
int mid = (pl + pr) >> 2;
//搜索算法
build(ls(p), pl, mid);
build(rs(p), mid + 1, pr);
//直到叶子节点,递归回根节点的路上更新沿路区间和,即tree[p]的值
pushup(p);
} //lazy_tag算法
void addtag(ll p,ll pl,ll pr,ll d) {
tag[p] += d;
tree[p] += (pl - pr + 1) * d;
} //向下传递函数
void pushdown(ll p, ll pl, ll pr) {
if (tag[p]) {
//如果子节点有tag[p],则一直传递直到叶子节点
int mid = (pl + pr);
addtag(ls(p), pl, mid,tag[p]);
addtag(rs(p), mid + 1, pr,tag[p]);
tag[p] = 0;
}
} //更新操作
void update(ll L, ll R, ll p, ll pl, ll pr, ll d) {
if (L <= pl && R >= pr) {
addtag(p, pl, pr, d);
return;
}
int mid = (pl + pr) >> 1; //这个是左中位数,所以下面的等号使用是有讲究的,原理类似于二分法,感兴趣的同学可自行查阅
if (L <= mid) update(L, R, ls(p), pl, mid, d);
if (R > mid) update(L, R, rs(p), mid + 1, pr, d);
//更新之后任然需要将更新信息传给与更新路径相关的节点
pushup(p);
} //查询操作
ll query(ll L, ll R, ll p, ll pl, ll pr) {
if (L <= pl && R >= pr) {
return tree[p];
}
//将tag标记传递下去
pushdown(p, pl, pr);
ll res = 0;
int mid = (pl + pr) >> 1;
if (L <= mid) res += query(L, R, ls(p), pl, mid);
if (R > mid) res += query(L, R, rs(p), mid + 1, pr);
return res;
} int main() {
ll n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
while (m--) {
ll q, l, r, d; cin >> q;
if (q == 1) {
cin >> l >> r >> d;
update(l, r, 1, 1, n, d);
}
if (q == 2) {
cin >> l >> r;
query(l, r, 1, 1, n);
}
}
return 0;
}

线段树 ----洛谷p3372的更多相关文章

  1. 线段树 洛谷P3932 浮游大陆的68号岛

    P3932 浮游大陆的68号岛 题目描述 妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活. 换用更高尚的说法,是随时准备着为这个无药可救的世界献身. 然而孩子们的生活却总是无忧无 ...

  2. [线段树]洛谷P5278 算术天才⑨与等差数列

    题目描述 算术天才⑨非常喜欢和等差数列玩耍. 有一天,他给了你一个长度为n的序列,其中第i个数为a[i]. 他想考考你,每次他会给出询问l,r,k,问区间[l,r]内的数从小到大排序后能否形成公差为k ...

  3. 区间连续长度的线段树——洛谷P2894 [USACO08FEB]酒店Hotel

    https://www.luogu.org/problem/P2894 #include<cstdio> #include<iostream> using namespace ...

  4. 洛谷P3372/poj3468(线段树lazy_tag)(询问区间和,支持区间修改)

    洛谷P3372 //线段树 询问区间和,支持区间修改 #include <cstdio> using namespace std; struct treetype { int l,r; l ...

  5. 洛谷P3372 【模板】线段树 1

    P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...

  6. 洛谷P3372线段树1

    难以平复鸡冻的心情,虽然可能在大佬眼里这是水题,但对蒟蒻的我来说这是个巨大的突破(谢谢我最亲爱的lp陪我写完,给我力量).网上关于线段树的题解都很玄学,包括李煜东的<算法竞赛进阶指南>中的 ...

  7. 洛谷P3372线段树模板1——线段树

    题目:https://www.luogu.org/problemnew/show/P3372 线段树模板. 代码如下: #include<iostream> #include<cst ...

  8. 洛谷 P3372 【模板】线段树 1

    P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...

  9. 洛谷—— P3372 【模板】线段树 1

    P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...

  10. 线段树入门详解,洛谷P3372 【模板】线段树 1

    关于线段树: 本随笔参考例题      P3372 [模板]线段树 1 所谓线段树就是把一串数组拆分成一个一个线段形成的一棵树. 比如说像这样的一个数组1,2,3,4,5: 1 ~ 5 /       ...

随机推荐

  1. CF466E Information Graph 题解

    题目链接 Luogu Codeforces 题意简述 某公司中有 \(n\) 名员工.为方便起见,将这些员工从 1 至 \(n\) 编号.起初,员工之间相互独立.接下来,会有以下 \(m\) 次操作: ...

  2. 常用ffmpeg命令集合(收藏吧,帮你省一个录屏软件的会员费)

    录制屏幕: 全屏的话用screen-capture-recoder下载地址:https://github.com/rdp/screen-capture-recorder-to-video-window ...

  3. 搭建lnmp环境-redis(第四步)

    1.下载epel仓库 (前面安装过了) yum install epel-release -y 2.下载redis数据库 yum install redis -y 3.启动redis服务 system ...

  4. centos7 扩展硬盘

    新增硬盘后 fdisk -l fdisk /dev/sdb (以后再加改成c) 阿里云叫vdb fdisk -l 注意,最好跟第一块硬盘一样! df -T 查看硬盘分区格式 注意,文件夹不能已存在的! ...

  5. STM32开发环境配置记录——关于PlatformIO + VSCode + CubeMX的集成环境配置

    前言 ​ 为什么配置这样的一个环境呢?鄙人受够了Keil5那个简陋的工作环境了,实在是用不下去,调试上很容易跟CubeMX的代码产生不协调导致调试--发布代码不一致造成的一系列问题.CubeIDE虽说 ...

  6. 【Python】Word文档操作

    依赖库下载: pip install python-docx -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install docx2pdf -i ...

  7. 【Kafka】02 原生集群部署

    基于大数据教程的环境: 192.168.101.11 centos7-01 192.168.101.12 centos7-02 192.168.101.13 centos7-03 搭建Kafka环境需 ...

  8. 【CentOS】 8版本 Cannot update read-only repo 问题

    GUI界面应用市场无法访问 https://blog.csdn.net/hm0406120201/article/details/104553205/

  9. 机器人操作系统ROS (学习视频)—— 学习ROS,安装Ubuntu,虚拟机和双系统如何选择

    分享一个ROS入门视频: https://www.bilibili.com/video/BV1BP4y1o7pw/

  10. 如何构建“集成神经网络”“Ensemble neural network”

    参考: https://arxiv.org/pdf/1603.05691.pdf 本文要讨论的是如何构建"集成神经网络"("Ensemble neural network ...