线段树模板12

线段树

洛谷上有两道线段树模板(指模板1,模板2)都是区间维护的,也就是说,都离不开lasytag的维护,为了提高效率,故使用了lasytag,这里看一下题

【模板】线段树 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某区间每一个数加上 k k k
  2. 求出某区间每一个数的和。

输入格式

第一行包含两个整数 n , m n, m n,m,分别表示该数列数字的个数和操作的总个数。

第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。

接下来 m m m 行每行包含 3 3 3 4 4 4 个整数,表示一个操作,具体如下:

  1. 1 x y k:将区间 [ x , y ] [x, y] [x,y] 内每个数加上 k k k
  2. 2 x y:输出区间 [ x , y ] [x, y] [x,y] 内每个数的和。

输出格式

输出包含若干行整数,即为所有操作 2 的结果。

样例 #1

样例输入 #1

5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4

样例输出 #1

11
8
20

提示

对于 30 % 30\% 30% 的数据: n ≤ 8 n \le 8 n8 m ≤ 10 m \le 10 m10
对于 70 % 70\% 70% 的数据: n ≤ 10 3 n \le {10}^3 n103 m ≤ 10 4 m \le {10}^4 m104
对于 100 % 100\% 100% 的数据: 1 ≤ n , m ≤ 10 5 1 \le n, m \le {10}^5 1n,m105

保证任意时刻数列中所有元素的绝对值之和 ≤ 10 18 \le {10}^{18} 1018

【样例解释】

分析1.1

操作很少,只有:

  • 区间加
  • 区间求和

我们用数组存储线段树每个节点的状态即可,看代码:

代码1

#include <bits/stdc++.h>
using namespace std;
const int M = 1e5+10;
#define int long long
int a[M];
struct segment {
#define lc(p) (p<<1)
#define rc(p) ((p<<1)|1)int tag[M << 2], sum[M << 2];void f(int o, int l, int r, int k) {tag[o] += k;sum[o] += k * (r - l + 1);}void push_up(int x) {sum[x] = sum[lc(x)] + sum[rc(x)];}void push_down(int o, int l, int r) {int mid = l + r >> 1;f(lc(o), l, mid, tag[o]);f(rc(o), mid + 1, r, tag[o]);tag[o] = 0;}void build(int o, int l, int r) {if (l == r) { sum[o] = a[l]; return; }int mid = l + r >> 1;build(lc(o), l, mid);build(rc(o), mid + 1, r);push_up(o);}int query(int ql, int qr, int o, int l, int r) {if (l>qr or r<ql) return 0;if (ql <= l and r <= qr) return sum[o];int ans = 0;int mid = l + r >> 1;push_down(o, l, r);ans += query(ql, qr, lc(o), l, mid);ans+=query(ql,qr,rc(o),mid+1,r);return ans;}void update(int ql,int qr,int o,int l,int r,int k){if (l>qr or r<ql) return;if(ql<=l and r<=qr) {f(o,l,r,k);return;}push_down(o,l,r);int mid = l + r >> 1;update(ql, qr, lc(o), l, mid,k);update(ql,qr,rc(o),mid+1,r,k);push_up(o);}
}t1;
signed main() {int n,m;cin >> n>>m;for (int i = 1; i <= n; i++) cin >> a[i];t1.build(1,1,n);for (int i=1;i<=m;i++){int x,y,k;cin>>x;if (x==1){cin>>x>>y>>k;t1.update(x,y,1,1,n,k);}else{cin>>x>>y;cout<<t1.query(x,y,1,1,n)<<endl;}}return 0;
}

分析1.2

我们只需要理解segment结构体

  • sum[i]表示线段树第i个节点对应的区间和
  • tag[i]就是节点i的懒标记

所以我们需要一个函数来标记节点,并修改此节点的和

void f(int o, int l, int r, int k) {tag[o] += k;sum[o] += k * (r - l + 1);}

f函数可以做到,它可以保存标记,并区间修改
当然标记需要下传,修改子节点后,父节点也要改变:

void push_up(int x) {sum[x] = sum[lc(x)] + sum[rc(x)];}

push_up可以重新求父节点的值

	void push_down(int o, int l, int r) {int mid = l + r >> 1;f(lc(o), l, mid, tag[o]);f(rc(o), mid + 1, r, tag[o]);tag[o] = 0;}

push_down可以下传标记
而查询与更新只要递归查询,合并答案即可

【模板】线段树 2

题目描述

如题,已知一个数列,你需要进行下面三种操作:

  • 将某区间每一个数乘上 x x x
  • 将某区间每一个数加上 x x x
  • 求出某区间每一个数的和。

输入格式

第一行包含三个整数 n , q , m n,q,m n,q,m,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 n n n 个用空格分隔的整数,其中第 i i i 个数字表示数列第 i i i 项的初始值。

接下来 q q q 行每行包含若干个整数,表示一个操作,具体如下:

操作 1 1 1: 格式:1 x y k 含义:将区间 [ x , y ] [x,y] [x,y] 内每个数乘上 k k k

操作 2 2 2: 格式:2 x y k 含义:将区间 [ x , y ] [x,y] [x,y] 内每个数加上 k k k

操作 3 3 3: 格式:3 x y 含义:输出区间 [ x , y ] [x,y] [x,y] 内每个数的和对 m m m 取模所得的结果

输出格式

输出包含若干行整数,即为所有操作 3 3 3 的结果。

样例 #1

样例输入 #1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

样例输出 #1

17
2

提示

【数据范围】

对于 30 % 30\% 30% 的数据: n ≤ 8 n \le 8 n8 q ≤ 10 q \le 10 q10
对于 70 % 70\% 70% 的数据:$n \le 10^3 , , q \le 10^4$。
对于 100 % 100\% 100% 的数据: 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105 1 ≤ q ≤ 1 0 5 1 \le q \le 10^5 1q105

除样例外, m = 571373 m = 571373 m=571373

(数据已经过加强 _

样例说明:

故输出应为 17 17 17 2 2 2 40 m o d 38 = 2 40 \bmod 38 = 2 40mod38=2)。

分析2

多了个乘法,再开数组代码逻辑会乱一点,但开个结构体即可:

struct node{int sum,mul,add;
};

不难想到,sum为区间和,mul为乘法懒标记,add为加法懒标记,对于一个区间x,可以存在子节点y,y应该接受懒标记:
y s u m = ( y s u m ∗ x m u l ) + x a d d ∗ ( y r − y l + 1 ) y_{sum}=(y_{sum}*x_{mul})+x_{add}*(y_r-y_l+1) ysum=(ysumxmul)+xadd(yryl+1)
修改y的懒标记:
y m u l = y m u l ∗ x m u l y_{mul}=y_{mul}*x_{mul} ymul=ymulxmul
y a d d = y a d d ∗ x m u l + x a d d y_{add}=y_{add}*x_{mul}+x_{add} yadd=yaddxmul+xadd

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rc(x) ((x<<1)|1)
#define lc(x) (x<<1)
const int M = 1e6;
const int N=1e18;
int a[M],n,m,mod;
void read(){cin>>n;cin>>m>>mod;for (int i=1;i<=n;i++) cin>>a[i];
}
struct node{int sum,mul,add;
};
struct segment{node seg[M<<2];void push_up(int x){seg[x].sum=seg[lc(x)].sum+seg[rc(x)].sum;}void build(int o,int l,int r){seg[o].mul=1;seg[o].add=0;if (l==r){seg[o].sum=a[l];return;}int mid=(l+r)>>1;build(lc(o),l,mid);build(rc(o),mid+1,r);push_up(o);}void f(int o,int l,int r,int add,int mul){seg[o].mul=(seg[o].mul*mul)%mod;seg[o].add=(seg[o].add*mul)%mod;seg[o].add=(seg[o].add+add)%mod;seg[o].sum=(seg[o].sum*mul)%mod;seg[o].sum=(seg[o].sum+(r-l+1)*add)%mod;}void push_down(int o,int l,int r){int mid=(l+r)>>1;f(lc(o),l,mid,seg[o].add,seg[o].mul);f(rc(o),mid+1,r,seg[o].add,seg[o].mul);seg[o].add=0;seg[o].mul=1;}void update(int ql,int qr,int add,int mul,int o=1,int l=1,int r=n){if (ql<=l and r<=qr) {f(o,l,r,add,mul);return;}int mid=(l+r)>>1;push_down(o,l,r);if(ql<=mid) update(ql,qr,add,mul,lc(o),l,mid);if(qr>=1+mid)update(ql,qr,add,mul,rc(o),mid+1,r);push_up(o);}int query(int ql,int qr,int o=1,int l=1,int r=n){if (ql<=l and r<=qr) return seg[o].sum;int mid=(l+r)>>1,ans=0;push_down(o,l,r);if (ql<=mid) ans=(ans+query(ql,qr,lc(o),l,mid))%mod;if (mid+1<=qr) ans=(ans+query(ql,qr,rc(o),mid+1,r))%mod;push_up(o);return ans;}
}T1;
void solve(){int opt,x,y,k;cin>>opt>>x>>y;switch(opt){case 1:{cin>>k;T1.update(x,y,0,k);break;}case 2:{cin>>k;T1.update(x,y,k,1);break;}default:cout<<T1.query(x,y)<<endl;}
}
signed main(){ios::sync_with_stdio(false);read();T1.build(1,1,n);while(m--) solve();return 0;
}

与线段树1大致相同,不再过多赘述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uni-app:实现数字文本框,以及左右加减按钮

效果 代码 <template><view><view classline3><view classline3_position><view classleft>数量<text>*</text></view> <view class"right"><view class"quantity_btn"><view class"…

Mysql存储引擎InnoDB

一、存储引擎的简介 MySQL 5.7 支持的存储引擎有 InnoDB、MyISAM、Memory、Merge、Archive、Federated、CSV、BLACKHOLE 等。 1、InnoDB存储引擎 从MySQL5.5版本之后&#xff0c;默认内置存储引擎是InnoDB&#xff0c;主要特点有&#xff1a; &#xff08;1&#xff09;灾难恢…

Docker入门——保姆级

Docker概述 ​ —— Notes from WAX through KuangShen 准确来说&#xff0c;这是一篇学习笔记&#xff01;&#xff01;&#xff01; Docker为什么出现 一款产品&#xff1a;开发—上线 两套环境&#xff01;应用环境如何铜鼓&#xff1f; 开发 – 运维。避免“在我的电脑…

【肺炎分类数据集】数据量非常充足的新冠肺炎分类数据共享

一、肺炎数据集介绍&#x1f349;&#xff1a; 1.1 格式&#x1f388; 按照标准的格式分为了①训练集train&#xff08;134138575198张&#xff09;&#xff0c;②验证集val&#xff08;8816张&#xff09;&#xff0c;③测试集test&#xff08;234390624张&#xff09;&#…

C++学习笔记总结练习:正则表达式

正则表达式 目录 regex正则表达式的定义regex_match/search/replace正则表达式的三个操作smatch、sregex_iterator正则表达式的结果对象以及与其配套的迭代器。 参考文献 正则表达式总结 1 正则表达式基础 不考虑子表达式的内容 头文件 #include<regex>库组件 库组件作…

React Dva项目 简单引入models中的所有JS文件

我们前面接触的 Dva项目 models目录下的文件还要一个一个引入 其实体验并不是很好 而且如果项目很大那就比较麻烦了 我们可以在 models 下创建一个 index.js 文件 编写代码如下 const context require.context("./", false, /\.js$/); export default context.key…

冠达管理:A股三大指数震荡整理 机构看好反弹趋势延续

周一&#xff0c;沪深两市呈弱势震动格式&#xff0c;创业板指领跌。到收盘&#xff0c;上证综指跌0.59%&#xff0c;报3268.83点&#xff1b;深证成指跌0.83%&#xff0c;报11145.03点&#xff1b;创业板指跌1%&#xff0c;报2240.77点。 资金面上&#xff0c;沪深两市昨日合计…

梳理日常开发涉及的负载均衡

负载均衡是当前分布式微服务时代最能提及的词之一&#xff0c;出于对分层、解耦、弱依赖、可配置、可靠性等概念的解读&#xff0c;一对一的模式变得不再可信赖&#xff0c;千变万化的网络环境中&#xff0c;冗余和备份显得格外重要&#xff0c;稍大型的系统就会存在大量微服务…

docker小白第一天

docker小白第一天 docker是什么docker理念容器与虚拟机比较docker能干什么docker官网介绍docker的基本组成docker平台架构 docker是什么 系统平滑移植&#xff0c;容器虚拟化技术。即源代码配置环境版本&#xff0c;打个包形成一个镜像文件&#xff0c;即软件带环境一起安装&a…

【果树农药喷洒机器人】Part1:研究现状分析以及技术路线介绍

本专栏介绍&#xff1a;付费专栏&#xff0c;持续更新机器人实战项目&#xff0c;欢迎各位订阅关注。 关注我&#xff0c;带你了解更多关于机器人、嵌入式、人工智能等方面的优质文章&#xff01; 文章目录 一、项目背景二、国内外研究现状2.1 国内研究现状2.2 国外研究现状 三…

RISC-V架构的演变

随着苹果基于ARM的硅和新的RISC-V CPU的推出&#xff0c;对于CPU开发来说&#xff0c;这是一个令人兴奋的时刻&#xff0c;尽管开发人员的旅程目前对后者来说有点坎坷。 我最喜欢的理论是&#xff0c;没有发生是孤独的&#xff0c;而只是重复了以前发生过的事情&#xff0c;也…

Linux 远程登录

Linux 远程登录 Linux 一般作为服务器使用&#xff0c;而服务器一般放在机房&#xff0c;你不可能在机房操作你的 Linux 服务器。 这时我们就需要远程登录到Linux服务器来管理维护系统。 Linux 系统中是通过 ssh 服务实现的远程登录功能&#xff0c;默认 ssh 服务端口号为 2…

C++QT教程1——QT概述(下载与安装)

文章目录 1 Qt概述1.1 什么是Qt1.2 Qt的发展史1.3 Qt版本1.4 Qt的下载与安装下载地址&#xff1a;其实我是有点懵逼的&#xff0c;因为还有个qtcreator&#xff0c;我差点不知道下哪个。。。&#xff08;qt框架比qtcreator功能更多更强大&#xff09; 安装 1.5 Qt的优点1.6 QT成…

SpringBoot + Docker 实现一次构建到处运行~

一、容器化部署的好处 图片 Docker 作为一种新兴的虚拟化方式&#xff0c;它可以更高效的利用系统资源&#xff0c;不需要进行硬件虚拟以及运行完整操作系统等额外开销。 传统的虚拟机技术启动应用服务往往需要数分钟&#xff0c;而 Docker 容器应用&#xff0c;由于直接运行…

[数据分析大全]基于Python的数据分析大全——Numpy基础

目录 一、前言二、NumpyNumpy数组 二、创建数组初始化占位符 三、输入、输出3.1 保存与载入文本文件3.2 保存与载入磁盘上的文件 四、数据类型五、数组信息六、调用帮助七、数组计算7.1 算数运算7.2 比较7.3 聚集函数 八、数组复制九、数组排序十、子集、切片、索引相关实现10.…

深入大B行业,什么是最有力的敲门砖?

引言&#xff1a;2023上半年&#xff0c; 能扛过外部环境各种变化&#xff0c; 这样的科技公司就很不容易了。 【全球云观察 &#xff5c; 热点关注】在当前后疫情时代下&#xff0c;全球经济增长处于的低增长期&#xff0c;这对所有科技企业的发展带来了直接影响。 有业内人…

win10 2022unity设置中文

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言解决方法 前言 在Edit->preferences里找不到language选项。 解决方法 【1】打开下面地址 注意 :把{version}换成你当前安装的版本&#xff0c;比如说如果…

SpringBoot第33讲:SpringBoot集成ShardingJDBC - 基于JPA的读写分离

SpringBoot第33讲&#xff1a;SpringBoot集成ShardingJDBC - 基于JPA的读写分离 本文是SpringBoot第33讲&#xff0c;主要介绍分表分库&#xff0c;以及SpringBoot集成基于 ShardingJDBC 的读写分离实践 文章目录 SpringBoot第33讲&#xff1a;SpringBoot集成ShardingJDBC - 基…

天津最新python培训班就业形势 python能就业吗?

小编认为Python是一门非常适合学习的编程语言&#xff0c;无论性别如何。它易于学习、功能强大&#xff0c;并且在各个领域都有广泛的应用&#xff0c;因此&#xff0c;性别不应该成为学习Python的障碍&#xff0c;那么学习Python是否就能找到满意的工作呢&#xff1f; 这是一…