线段树模板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,一经查实,立即删除!

相关文章

JavaScript--WebStorage

目录 WebStorage概述 WebStorage分类 注意&#xff1a; localStorage方法 介绍&#xff1a; 常见方法&#xff1a; 案例演示&#xff1a; sessionStorage方法 介绍&#xff1a; 常见方法&#xff1a; 案例演示&#xff1a; WebStorage概述 WebStorage是HTML5中…

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;灾难恢…

git 如何切换到远程分支(remote)分支

要切换到远程分支&#xff0c;你可以按照以下步骤操作&#xff1a; 首先&#xff0c;使用git branch -r命令查看可用的远程分支列表。 选择你要切换到的远程分支&#xff0c;然后使用以下命令创建并切换到一个新的本地分支&#xff1a; git checkout -b <branch_name> o…

Docker入门——保姆级

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

理解和使用Ansible模块,简化自动化任务

Ansible是一款强大的自动化工具&#xff0c;用于管理和配置IT基础设施。在Ansible的世界中&#xff0c;模块&#xff08;Module&#xff09;是至关重要的组成部分。本文将深入探讨Ansible模块&#xff0c;了解它们如何简化自动化任务的执行过程。 Ansible模块是Ansible的核心组…

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

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

如何使用第三方库CryptoJS来计算base64二进制原文的SM3算法十六进制哈希值

1、引入CryptoJS库。 <script src"https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>2、将base64字符串转换为字节数组。你可以使用CryptoJS.enc.Base64.parse()方法来实现&#xff1a; var base64Text "SGV…

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…

乐鑫科技 2022 笔试面试题

岗位:嵌入式软件实习生。 个人情况:本科双非电子信息工程,硕士华五软件工程研一在读;本科做过一些很水的项目 ,也拿项目搞了一些奖,相对来说嵌入式方向比较对口。 时间线及面试流程 2021.04.02 笔试 题目分为选择题和编程题,选择题二十题,编程题两题; 选择题基本…

【Go】Go数据操作 - 处理JSON文件

目录 何为JSON 编码JSON 解码JSON 延伸拓展 何为JSON JSON (JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。JSON最初是 JavaScript的一部分&#xff0c;后由于便于快速编写的特性&#xff0c;被开发者独立出来。基本上所有的语言都支持JSON数据的…

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

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

量化交易中的股票接口技术解析

在当今数字化金融时代&#xff0c;股票接口成为连接量化交易策略与金融市场的桥梁&#xff0c;为投资者提供了高效、准确的数据获取和交易执行功能。 一、股票接口的基本原理&#xff1a; 股票接口是量化交易系统的核心组成部分&#xff0c;它负责连接投资者的交易程序与金融市…

【力扣周赛】第357场周赛

【力扣周赛】第357场周赛 2810. 故障键盘题目描述解题思路 2811. 判断是否能拆分数组题目描述解题思路 2810. 故障键盘 题目描述 描述&#xff1a;你的笔记本键盘存在故障&#xff0c;每当你在上面输入字符 ‘i’ 时&#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;也…