【算法学习】线段树基础版

一 线段树

1.概念

线段树可以理解为一个二叉树,如果是利用线段树求区间的和,那么每个结点的权值维护的是结点所维护区间的和,再将该区间一分为二,分别交由左右儿子维护。

拿区间1 - 4的和来举例子,

根结点维护的是区间1 到 4,结点权值是该区间的和,再将区间一份为二,其左儿子维护的是 1 - 2,右儿子维护的是 3 - 4 ,以此类推,直到结点维护的区间长度为1。

不难看出,每个节点的权值等于左右儿子的权值之和。

2.基本步骤

1.构造线段树

清楚了线段树的概念后,很容易构造线段树,一般算法题都是通过数组模拟二叉树,本文也采用这种方式。

struct Tree {int l, r, weight;
} tree[N];
using namespace std;void build_tree(int i, int l, int r) {if (l == r) {tree[i] = {l, r, w[l]};return;}int mid = l + r >> 1;//构建左子树build_tree(i<<1, l, mid);//构建右子树build_tree(i<<1|1, mid + 1, r);//节点权值int sum = tree[i * 2].weight + tree[i * 2 + 1].weight;//更新区间tree[i] = {l,r,sum};}
2.区间查询

从根节点开始找目标区间

1.结点维护的区间是目标区间的子集,直接返回结点权值

2.左子树与目标区间有交集,递归左子树

2.右子树与目标区间有交集,递归右子树

4.返回sum

拿查找2-3区间和举例

从根节点开始,目标区间和左子树有交集,递归左子树,目标区间和右子树有交集 ,递归右子树;

接着看根节点左儿子,目标区间只和右子树有交集,递归右子树,

看根节点右儿子,目标区间只和左子树有交集,递归左子树, 

再向下递归发现,节点维护区间刚好是目标区间的子集,直接返回权值,结束向下递归。

代码

int query(int i,int l,int r){//结点维护区间是目标区间的子集,直接返回权值if(tree[i].l>=l&&tree[i].r<=r)return tree[i].weight;int mid = tree[i].l + tree[i].r >>1;int sum = 0;if(l<=mid) sum += query(i*2,l,r);if(r>mid)sum+= query(i*2+1,l,r);return sum;
}

3.区间修改 

从根节点开始找目标区间

1.结点维护的区间是目标区间的子集,修改权值,返回

2.左子树与目标区间有交集,递归左子树

2.右子树与目标区间有交集,递归右子树

4.更新结点权值(pushup)

拿给2-3区间加1和举例

从根节点开始,目标区间和左子树有交集,递归左子树,目标区间和右子树有交集 ,递归右子树;

接着看根节点左儿子,目标区间只和右子树有交集,递归右子树,

看根节点右儿子,目标区间只和左子树有交集,递归左子树, 

再向下递归发现,节点维护区间刚好是目标区间的子集,直接修改权值,结束向下递归。

代码

void pushup(int i){tree[i].weight = tree[i<<1].weight + tree[i<<1|1].weight;
}
void modify(int i, int l, int r,int v)
{if(tree[i].l>=l&&tree[i].r<=r) tree[i].weight+=v*(tree[i].r - tree[i].l+1);else{int mid = tree[i].l + tree[i].r >>1;if(l<=mid) modify(i<<1,l,r,v);if(r>mid) modify(i<<1|1,l,r,v);pushup(i);}}

例题

1.动态求连续区间和

给定 n 个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列[a,b]的连续和。

输入格式

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

第二行包含n个整数,表示完整数列。

接下来 m 行,每行包含三个整数k, a, b(k = 0,表示求子数列[a, b]的和;k = 1,表示第 a 个数加b)。

数列从1开始计数。

输出格式

输出若干行数字,表示k=0 时,对应的子数列[a, b]的连续和。

数据范围

1≤n≤100000,

1≤m≤100000,

1≤a≤b≤n,

数据保证在任何时候,数列中所有元素之和均在 int 范围内。

输入样例:

10 5
1 2 3 4 5 6 7 8 9 10
1 1 5
0 1 3
0 4 8
1 7 5
0 4 8
1
2
3
4
5
6
7
输出样例:

11
30
35
1
2
3

ans

#include <cstdio>
#include <iostream>
#include <algorithm>const int N = 1e5 + 10;
struct segment_tree {int l, r, weight;
} tree[N*4];
int n,m;
int w[N];
using namespace std;void build_tree(int i, int l, int r) {if (l == r) {tree[i] = {l, r, w[l]};return;}int mid = l + r >> 1;//构建左子树build_tree(i<<1, l, mid);//构建右子树build_tree(i<<1|1, mid + 1, r);//节点权值int sum = tree[i * 2].weight + tree[i * 2 + 1].weight;//更新区间tree[i] = {l,r,sum};}
void pushup(int i){tree[i].weight = tree[i<<1].weight + tree[i<<1|1].weight;
}
int query(int i,int l,int r){//结点维护区间是目标区间的子集,直接返回权值if(tree[i].l>=l&&tree[i].r<=r)return tree[i].weight;int mid = tree[i].l + tree[i].r >>1;int sum = 0;if(l<=mid) sum += query(i<<1,l,r);if(r>mid)sum+= query(i<<1|1,l,r);return sum;
}void modify(int i, int l, int r,int v)
{if(tree[i].l>=l&&tree[i].r<=r) tree[i].weight+=v*(tree[i].r - tree[i].l+1);else{int mid = tree[i].l + tree[i].r >>1;if(l<=mid) modify(i<<1,l,r,v);if(r>mid) modify(i<<1|1,l,r,v);pushup(i);}}
int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);build_tree(1, 1, n);int k, a, b;while (m -- ){scanf("%d%d%d", &k, &a, &b);if (k == 0) printf("%d\n", query(1, a, b));else modify(1, a,a, b);}return 0;
}

感谢你的阅读,希望本文对你有所帮助。 

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

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

相关文章

JavaEE——Spring Boot入门

目录 &#x1f4da; JavaEE——Spring Boot入门 &#x1f527; 1. 新建Spring Boot项目 &#x1f6e0; 2. 添加pom依赖 &#x1f4dd; 3. 添加application.yml文件 &#x1f4c2; 4. 创建Dao层 &#x1f527; 5. 创建Service层 &#x1f5a5;️ 6. 创建Controller层及HT…

使用ClassFinal实现springboot项目jar包加密

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

docker容器技术篇:集群管理实战mesos+zookeeper+marathon(二)

docker集群管理实战mesoszookeepermarathon&#xff08;二&#xff09; 一 实验环境 操作系统&#xff1a;centos7.9 二 基础环境配置以及安装mesos 安装过程请点击下面的链接查看&#xff1a; 容器集群管理实战mesoszookeepermarathon&#xff08;一&#xff09; 三 安装…

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 4月27日,星期六

每天一分钟&#xff0c;知晓天下事&#xff01; 2024年4月27日 星期六 农历三月十九 1、 教育部&#xff1a;深入实施学生欺凌防治专项行动&#xff0c;对所有中小学校开展起底式大排查。 2、 商务部等七部门联合印发《汽车以旧换新补贴实施细则》&#xff0c;购车最高补贴1万…

【VBA】获取指定目录下的Excel文件,并合并所有excel中的内容。

1.新建一个excel表格。并创建两个Sheet&#xff0c;名字分别命名为FileList 和 All information。 2.按ALTF11进入 VBA编程模块&#xff0c;插入模块。 3.将如下 第五部分代码复制到模块中。 点击运行即可&#xff0c;然后就能提取指定目录下的所有excel文件信息并合并到一起…

连接oracle时出现ORA-12541:TNS:无监听程序的错误

遇到个问题&#xff0c;有一台windows serve 的服务器&#xff0c;这台服务器&#xff08;只部署了oracle&#xff09;忽然监听出问题了&#xff0c;提示 一、问题检查步骤&#xff1a; 1.winR--->cmd--->输入 lsnrctl status 查看监听的状态 如果监听器未运行&#…

【01】JAVASE-Java基础入门【从零开始学JAVA】

Java零基础系列课程-JavaSE基础篇 Lecture&#xff1a;波哥 Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。…

移远通信再推系列高性能卫星、5G、GNSS及三合一组合天线

4月23日&#xff0c;全球领先的物联网整体解决方案供应商移远通信正式宣布&#xff0c;再次推出多款高性能天线产品&#xff0c;以进一步满足物联网市场对高品质天线产品的需求。 其中包括卫星天线YETN001L1A、三合一组合天线YEMA300QXA和YEMN302Q1A&#xff0c;外部5G天线YECN…

windows环境下搭建Sqli-Labs靶场

目录 靶场介绍&#xff1a; 一&#xff0c;PHPstudy下载&#xff0c;安装 二&#xff0c;SQLI-LABS靶场上传 靶场介绍&#xff1a; SQLi-LABS 是一款SQL注入的靶场环境&#xff0c;共有75关&#xff0c;是网安入门、进阶必打的一款靶场&#xff1b; 下面的测试场景都支持GE…

MIGO行项目屏幕增强

MIGO行项目屏幕增强 一、增强描述 由于在事务码MIGO中存在的字段中没有能够满足客户需求的字段&#xff0c;所以需要在事务码MIGO的屏幕中添加一个新的页签用来保存物料凭证中行项目增加的字段。 通过查找BADI的程序ZDEMO_BADI,输入参数MIGO后&#xff0c;得到对应BADI为MB_M…

16 - grace数据处理 - 补充 - 读GRACE数据并进行低阶项替换

16 - grace数据处理 - 补充 - 读GRACE数据并进行低阶项替换 *0* 引言*1* 主程序分享0 引言 关于Grace模型数据的介绍可以参考文章00,数据由3家机构发布,这里做一个关于数据读取的补充,源码来自这里,直接运行slepian_delta中的程序会出现😊意想不到😊的错误,下面分享的…

虚拟化及Docker基础

一、虚拟化 1.1 云端 1.2 云计算服务模式分层 1.3 虚拟化架构 1.3.1 寄居架构 1.3.2 原生架构 1.4 虚拟化产品 1.4.1 仿真虚拟化产品&#xff08;对系统硬件没有要求&#xff0c;性能最低&#xff09; 1.4.2 半虚拟化 &#xff08;虚拟机可以使用真机物理机&#xff09…

【GitHub】github学生认证,使用copilot教程

github学生认证并使用copilot教程 写在最前面一.注册github账号1.1、注册1.2、完善你的profile 二、Github 学生认证 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&a…

详细分析MySQL中的distinct函数(附Demo)

目录 前言1. 基本知识2. 基础Demo3. 进阶Demo 前言 该函数主要用于去重&#xff0c;对于细节知识&#xff0c;此文详细补充说明 1. 基本知识 DISTINCT 是一种用于查询结果中去除重复行的关键字 在查询数据库时&#xff0c;可能会得到重复的结果行&#xff0c;但有时只需要这…

[c++]菱形继承解析

菱形继承 大概示意图&#xff1a; 菱形继承不一定只是标准的菱形&#xff0c;只要形似菱形的都可以叫菱形继承。 (以下说明都是默认公有继承&#xff0c;public和protected成员情况下) 菱形继承会造成数据的冗余和二义性&#xff1a; 冗余&#xff1a;一个Assitant对象里面有…

详细分析PyInstaller打包python为exe执行文件(附Demo)

目录 前言1. 基本知识2. Demo 前言 需要将python文件打包成exe文件&#xff0c;变成rpa自动化形式 1. 基本知识 PyInstaller是一个用于将Python应用程序打包成独立可执行文件的工具 可以将Python脚本打包成Windows、Linux和Mac OS X上的可执行文件&#xff0c;这个作用可以将…

ThingsBoard远程RPC调用设备

使用 RPC 功能 客户端 RPC 从设备发送客户端 RPC 平台处理客户端RPC 服务器端 RPC 服务器端RPC结构 发送服务器端RPC 使用 RPC 功能 ThingsBoard 允许您从服务器端应用程序向设备发送远程过程调用 (RPC)&#xff0c;反之亦然。基本上&#xff0c;此功能允许您向设备发送命…

Python 数组控件的使用

当一个UI窗口界面内有多个相同类型的控件&#xff0c;且这多个控件的功能都类似时&#xff0c;使用数组控件是一个非常不错的选择&#xff0c;可以大大减少代码的编写 且 代码易读性强&#xff0c;可惜的是Python好象是没有数组控件这个东东。 我们来看看以下一个界面&#xff…

Linux:服务器硬件及RAID配置

文章目录 Linux&#xff1a;服务器硬件及RAID配置服务器服务器是什么服务器的结构 RAID硬RAID与软RAID对比RAID级别介绍RAID 0RAID 1RAID 5RAID 6RAID 10 RAID级别对比 配置RAID硬RAID软RAID Linux&#xff1a;服务器硬件及RAID配置 服务器 服务器是什么 服务器的英文名称为…

Linux进程概念(六):进程控制

目录 进程创建 fork函数 进程终止 终止时干了什么 进程终止的三种情况 main函数的返回值 打印默认退出码 自定义退出码 总结 进程终止 exit函数 _exit函数 exit和_exit的区别 进程等待 什么是进程等待 为什么要有进程等待 wait函数 waitpid函数 阻塞等待与…