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

一 线段树

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,一经查实,立即删除!

相关文章

开发管理导读

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、代码版本管理1、github代码版本管理2、gitlab代码版本管理3、SVN&#xff08;Subversion&#xff09;代码版本管理 二、代…

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…

【小浩算法cpp题解】合并两个有序链表(21)

目录 前言我的思路我的代码 前言 今天继续做链表相关的题目&#xff0c;考研期间练多了现在觉得这种题目真是简单。晚上如果有机会可以再做一个树的深度优先搜索。 我的思路 其实这道题的思路比较像排序中的二路归并&#xff0c;最核心的点是在归并的时候要防止断链,我的解决…

librosa 语音识别 学习笔记

目录 不错的功能介绍 librosa安装 语音识别 不错的功能介绍 librosa&#xff0c;一个很有趣的 Python 库&#xff01; - 简书 音频转特征向量 GitHub - librosa/librosa: Python library for audio and music analysis librosa安装 2024.04.27 测试ok Win11系统 pip in…

使用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…

渗透第一次作业

思考&#xff1a; 1. windows登录的明文密码&#xff0c;存储过程是怎么样的&#xff0c;密文存在哪个文件下&#xff0c;该文件是否可以打开&#xff0c;并且查看到密文 2. 我们通过hashdump 抓取出 所有用户的密文&#xff0c;分为两个模块&#xff0c;为什么&#xff1f; 这…

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…

RabbitMQ消息是如何分发的,消息是怎么路由的, RabbitMQ中的交换机类型有哪些

目录 面试官:讲一下RabbitMQ消息如何分发和消息怎么路由的?消息分发消息路由RabbitMQ中的交换机类型示例Spring Boot代码示例1. 直接路由(Direct Exchange)2. 扇出路由(Fanout Exchange)3. 主题路由(Topic Exchange)4. 头路由(Headers Exchange)该文章专注于面试,面…

【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;但有时只需要这…

【力扣】18. 四数之和

18. 四数之和 题目描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;…