问题描述:

已知一个数列,对数列进行两种操作: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. 数据仓库建模工具之一——Hive学习第三天

    1.Hive的基本操作 1.1 Hive库操作 1.1.1 创建数据库 1)创建一个数据库,数据库在HDFS上的默认存储路径是/hive/warehouse/*.db. create database ...

  2. 【JavaScript高级03】执行上下文和执行上下文栈

    1,函数提升和变量提升 编写以下代码: var a = 3 function fn () { console.log(a) var a = 4 } fn() 上面的JavaScript代码执行结果为一 ...

  3. JMeter While循环控制器应用之遍历获取文件参数

    While循环控制器应用之遍历获取文件参数 by: 授客 QQ:1033553122 测试环境 JMeter-5.4.1 应用 实现单线程在单次迭代内遍历获取文件参数 说明:上图仅给出关键配置信息 注 ...

  4. ABC354

    A link 模拟整个过程即可. 点击查看代码 #include<bits/stdc++.h> #define int long long using namespace std; sig ...

  5. 【Git】GithubDesktop 忽略文件无法忽略BUG

    问题描述: 从仓库拉取的[.gitignore]忽略配置文件,在项目跑起来之后会生成诸多.idea文件,target打包文件 一开始没有忽略,但是发现使用GD配置之后忽略无效: 解决办法: 做一次随便 ...

  6. 【Mybatis】Bonus02 补充

    关于主键生成问题 Mybatis的主键生成是基于JDBC的使用主键[getGeneratedKeys()]方法 也就是说,必须要JDBC驱动的支持才行 @Test public void junitT ...

  7. 【Layui】13 轮播 Carousel

    文档地址: https://www.layui.com/demo/carousel.html 基础轮播: <style> /* 为了区分效果 */ div[carousel-item]&g ...

  8. 在Ubuntu18.04系统中源码安装 gcc7.3.0

    本文给出源码安装gcc7.3.0的方法. 依赖的环境安装到自建文件夹下, 给出下面操作中环境的安装文件夹: /home/devilmaycry/anaconda3/mindspore_envs这个路径 ...

  9. VSCode 如何将已编辑好的python文件中的 tab 键缩进转换成4个空格键缩进

    事情起源: 使用vscode维护一个7年前的python项目,发现编辑后运行报错,提示缩进错误,原因是当时的项目使用tab做缩进,而我正在用的vscode是使用4空格做缩进,因此造成了缩进不匹配的问题 ...

  10. conda 安装pytorch

    配置:win 10 ,python=3.6 安装pytorch-1.1.0,cudatoolkit-9.0,torchvision-0.3.0. 出现的问题:import torch 的时候,出现了O ...