第五十八章 线段树(一)

news/2024/5/6 17:14:37/文章来源:https://blog.csdn.net/weixin_72060925/article/details/130037952

第五十八章 线段树(一)

  • 一、树状数组的缺陷
  • 二、线段树的作用
  • 三、线段树的基本构成
      • 1、节点定义
      • 2、线段树的结构
  • 四、线段树的重要函数
    • 1、构造线段树——bulid函数
    • 2、查询区间——query函数
    • 3、单点修改——modify函数
  • 五、例题

一、树状数组的缺陷

在前面两个章节中,我们利用树状数组去维护的是前缀和数组和差分数组。当我们去查询 区间和的时候,我们采用的方法是两个前缀和相减。也就是说,如果我们想求某个区间的性质就必须将其转化为两个前缀的性质相减。只有满足这个条件的时候,我们才能使用树状数组。但是有的性质并不满足这个条件,比如说我们想求一个区间最大值的时候,我们并不能将其转化为两个前缀的最大值相减。

所以说,当我们求某些特殊的区间性质的时候,树状数组就很难做到了。但是如果是求前缀的性质,树状数组还是很好用的。

那么为了解决高效求区间性质的问题,就需要用到今天所讲解的线段树。

二、线段树的作用

线段树能做到的恰恰就是树状数组不能做到的。线段树最重要的作用就是通过O(log(n))O(log(n))O(log(n))的时间复杂度去维护或查询某个区间的性质。

三、线段树的基本构成

1、节点定义

struct Node
{int l, r;//区间的左右端点int v;//该区间的性质
}

2、线段树的结构

线段树是一个二叉树。假设一个节点代表的区间是[l,r][l,r][l,r],然后我们将这个区间一分为2,左边的区间就是该节点的左子树,右边的区间就是该节点的右子树。
如下图所示:
在这里插入图片描述
(选自百度百科)

四、线段树的重要函数

1、构造线段树——bulid函数

void build(int u, int l, int r)
{tre[u] = {l, r};if(l == r)return;int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);
}

uuu指的是节点标号,lllrrr是该节点所代表的区间的左右端点。当我们的根节点标号是111的时候,我们的左右子节点分别是(2∗u)(2*u)(2u)(2∗u+1)(2*u+1)(2u+1),如果写成位运算的模式即:(u<<1)(u<<1)(u<<1)(u<<1∣1)(u<<1|1)(u<<1∣1)。最小的区间即区间左端点等于区间右端点的时候,此时该区间所在的树中节点也恰好是我们的叶子节点。

2、查询区间——query函数

在这里插入图片描述
如上图所示,假设我们的线段树维护的是区间的最大值,我们现在的目的是求红色区域所构成的区间的最大值。

想要求红色区间最大值的话,我们只需要找到图中三段的绿色区间的最大值,然后三个区间比较一下即可。

现在我们的难点是如何找到这三个绿色区间。

不难发现,这三个区间都是被红色区间包含的,所以只要某个节点所代表的区间被包含在我们所求区间里,我们就返回这个区间的最值,然后再所有返回的最值中比较一个最大值作为答案。

int query(int u, int l, int r)
{if(tre[u].l >= l && tre[u].r <= r)return tre[u].v;int mid = tre[u].l + tre[u].r >> 1;int res = 0;if(l <= mid)res = query(u << 1, l, r);if(r > mid)res = max(res, query(u << 1 | 1, l, r));return res;
}

3、单点修改——modify函数

单点修改的操作比较麻烦,我们可以将单点修改的操作画成下面的图。
在这里插入图片描述
假设上面这个图的最后一层就是叶子节点。叶子节点所代表的区间就是一个点,所以我们单点修改一定对应着某个叶子节点,我们现在的目的就是去找到这个点。然后对这个点进行修改。

这里还有一个问题,这个单点被包含在若干区间内,当我们修改了这个单点后,所有包含这个点的区间也需要被更新。也就是说我们在回溯的时候,还要利用子节点去更新一下父节点。这个利用子节点更新父节点操作写成:pushuppushuppushup

void pushup(int u)
{tre[u].v = max(tre[u << 1].v, tre[u << 1 | 1].v);
}void modify(int u, int x, int v)
{if(tre[u].l == x && tre[u].r == x)tre[u].v = v;else{int mid = tre[u].l + tre[u].r >> 1;if(x <= mid)modify(u << 1, x, v);elsemodify(u << 1 | 1, x, v);pushup(u);}
}

五、例题

AcWing1275. 最大数

参考代码:

#include<bits/stdc++.h>
#define endl '\n'
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5 + 10;
struct Node
{int l, r;int v;
}tre[4 * N];
int m, p;void build(int u, int l, int r)
{tre[u] = {l, r};if(l == r)return;int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);
}int query(int u, int l, int r)
{if(tre[u].l >= l && tre[u].r <= r)return tre[u].v;int mid = tre[u].l + tre[u].r >> 1;int res = 0;if(l <= mid)res = query(u << 1, l, r);if(r > mid)res = max(res, query(u << 1 | 1, l, r));return res;
}void pushup(int u)
{tre[u].v = max(tre[u << 1].v, tre[u << 1 | 1].v);
}void modify(int u, int x, int v)
{if(tre[u].l == x && tre[u].r == x)tre[u].v = v;else{int mid = tre[u].l + tre[u].r >> 1;if(x <= mid)modify(u << 1, x, v);elsemodify(u << 1 | 1, x, v);pushup(u);}
}void solve()
{int n = 0, last = 0;scanf("%lld%lld", &m, &p);build(1, 1, m);int x;char op[2];while (m -- ){scanf("%s%lld", op, &x);if (*op == 'Q'){last = query(1, n - x + 1, n);printf("%lld\n", last);}else{modify(1, n + 1, ((ll)last + x) % p);n ++ ;}}}signed main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();
}

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

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

相关文章

对于电商行业来讲,真正决定它的并不是规模,而是载体

纵然是在现在这样的情况之下&#xff0c;我们依然无法用「格局已定」来形容和阐述现在的电商市场格局。这一点&#xff0c;我们可以从以抖音、快手为代表的电商新势力的崛起当中&#xff0c;看出一丝端倪。对于电商行业来讲&#xff0c;真正决定它的并不是规模&#xff0c;而是…

Dart中的异步

一 事件循环 flutter 就是运行在一个root isolate 中 程序只要运行起来&#xff0c;就有一个事件循环一直在运行 &#xff0c;直至程序退出。 EventLoop 先从mrcro 对列中取任务&#xff0c;取完任务再去 event 队列中取任务。队列任务是FIFO。 二 认识Future abstract clas…

[JavaEE]----Spring03

文章目录Spring_day031&#xff0c;AOP简介1.1 什么是AOP?1.2 AOP作用1.3 AOP核心概念2&#xff0c;AOP入门案例2.1 需求分析2.2 思路分析2.3 环境准备2.4 AOP实现步骤步骤1:添加依赖步骤2:定义接口与实现类步骤3:定义通知类和通知步骤4:定义切入点步骤5:制作切面步骤6:将通知…

C++内存管理(new和delete)

目录 1. new/delete操作内置类型 2. new和delete操作自定义类型 3. operator new与operator delete函数 4 .new和delete的实现原理 1 .内置类型 2 .自定义类型 new的原理 delete的原理 new T[N]的原理 delete[]的原理 5. 定位new表达式(placement-new) 6. malloc/f…

使用Process Explorer和Clumsy定位软件高CPU占用问题

目录 1、问题描述 2、使用Process Explorer初步找到CPU占用高的原因 3、使用Clumsy工具在公司内网环境复现了问题 4、根据Process Explorer中的函数调用堆栈&#xff0c;分析源码&#xff0c;最终找出了问题 5、总结 在排查项目客户的视频图像闪烁问题时&#xff0c;无意中…

Centos7安装部署Jenkins

Jenkins简介&#xff1a; Jenkins只是一个平台&#xff0c;真正运作的都是插件。这就是jenkins流行的原因&#xff0c;因为jenkins什么插件都有 Hudson是Jenkins的前身&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控程序重复的工作&#xff0c;Hudson后来被…

JavaScript基础-02

常量&#xff08;字面量&#xff09;&#xff1a;数字和字符串 常量也称之为“字面量”&#xff0c;是固定值&#xff0c;不可改变。看见什么&#xff0c;它就是什么。 常量有下面这几种&#xff1a; 数字常量&#xff08;数值常量&#xff09;字符串常量布尔常量自定义常量…

【MATLAB数学建模编程实战】Kmeans算法编程及算法的简单原理

欢迎关注&#xff0c;本专栏主要更新MATLAB仿真、界面、基础编程、画图、算法、矩阵处理等操作&#xff0c;拥有丰富的实例练习代码&#xff0c;欢迎订阅该专栏&#xff01;&#xff08;等该专栏建设成熟后将开始收费&#xff0c;快快上车吧~~&#xff09; 【MATLAB数学建模编…

[LeetCode周赛复盘] 第 340 场周赛20230409

[LeetCode周赛复盘] 第 340 场周赛20230409 一、本周周赛总结二、 6361. 对角线上的质数1. 题目描述2. 思路分析3. 代码实现三、6360. 等值距离和1. 题目描述2. 思路分析3. 代码实现四、6359. 最小化数对的最大差值1. 题目描述2. 思路分析3. 代码实现五、 6353. 网格图中最少访…

ROS实践06 自定义消息类型

文章目录运行环境&#xff1a;思路&#xff1a;1.1 定义.msg文件1)功能包下新建 msg 目录&#xff0c;添加文件 Person.msg2)修改package.xml3)修改CMakeLists.txt2.1 自定义消息调用(C)1&#xff09;编译后修改includePath2&#xff09;发布方实现2.1修改CMakeLists.txt2.3运行…

【OpenCV-Python】cvui 之 trackbar

CVUI 之 trackbar cvui::trackbar() 渲染一个 trackbar&#xff0c; 可以左右拖动或点击对数字进行增加或减少的调整。 不使用离散间隔 使用离散间隔 Python import numpy as np import cv2 import cvuidef trackbar_test():WINDOW_NAME Trackbar-Test# 创建画布frame np.z…

【Python童年游戏】满满的回忆杀—那些年玩过的童年游戏你还记得吗?那个才是你的菜?看到第一个我就泪奔了(致我们逝去的青春)

导语 滴一一学生卡&#x1f64c; 结伴上车的学生仔子们 用笑声打破车厢的沉默 大人眼里的晚高峰 是给放学后快乐&#x1f600;时光的加时 下车的学生匆匆起身带起 一阵熟悉的栀子香于&#x1f493; 是关于校园的记忆 开始零零散散地闪现 放学后集合的秘密基地/跟着城…

LVGL v8学习笔记 |12 - 移植LVGL 8.3到ESP32C3开发板(ST7789)

一、移植前的准备 1. 基础工程 ESP32-IDF开发笔记 | 03 - 使用SPI外设驱动ST7789 SPILCD2. lvgl源码 https://github.com/lvgl/lvgl下载最新发布的 8.3.6 版本:https://github.com/lvgl/lvgl/releases/ 二、移植lvgl 1. 复制lvgl源码到工程中 将下载的 lvgl-8.3.6 文件夹直…

JSON数据遍历之for-in

JSON数据遍历之for-in object 本身就是无对象的集合&#xff0c;因此在用 for-in 语句遍历对象的属性时&#xff0c;遍历出的属性顺序与对象定义时不同。 W3C标准 根据 ECMA-262&#xff08;ECMAScript&#xff09;第三版中描述&#xff0c;for-in 语句的属性遍历的顺序是由对…

KlayGE-001-简介

KlayGE 引擎学习-001 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWlSlet9-1680688988724)(images/KlayGE_logo.png)] 一、KlayGE引擎介绍 软件简介 KlayGE中文译为&#xff1a;粘土游戏引擎&#xff0c;是一个开源、跨平台&#xff0c;基于插…

6-MATLAB APP Design-表格组件(uitable)

此博文通过MATLAB APP Design实现对学生成绩的处理,具体的功能包括读取表格数据、添加学生数据、计算总成绩、成绩排序+以及表格的保存。 一、APP 界面设计展示 1. 在画布中拖入面板、表格和四个按钮,布局如下。将面板的title写为“学生成绩计算器”并居中,将四个按钮的t…

游戏开发之Unity2021熟悉基本工具

接上一节通用渲染管线项目搭建 导入天空盒素材&#xff1a;在窗口中选择资源商店后会弹出下面的图片&#xff0c;在资源商店中找到我们想要的天空盒素材&#xff0c;将素材在unity中打开&#xff0c;如下面的第二幅图中就是我选择的天空盒素材&#xff0c;在这里可能会遇到一个…

Centos7搭建Ngrok内网穿透

一、安装gcc和git(用于下载ngrok源码) yum install gcc -y yum install git -y 二、安装go语言环境 yum install -y mercurial git bzr subversion golang golang-pkg-windows-amd64 golang-pkg-windows-386 三、检查环境安装 git --version //( > 1.7 ) go version 四…

通读《技术管理实战36讲》1、自我倾听篇

你好&#xff0c;我是小Z&#xff0c;一个工作在交付前线的程序员&#xff0c;我们正在通读《技术管理实战36讲》&#xff0c;作者刘建国。今天我们要梳理的章节是“自我倾听篇”。 在第1篇《多年前的那些工程师都去哪了&#xff1f;》中&#xff0c; 作者借助上周的“老知道人…

linux系统中cat命令的详细用法

在Linux中&#xff0c;cat命令是一个很常用的命令&#xff0c;它的作用是将文件内容输出到屏幕上&#xff0c;或者将多个文件合并成一个文件。下面是cat命令的一些常用用法&#xff1a; ​1. 显示文件内容 使用cat命令可以打印出文件的内容&#xff0c;如&#xff1a; cat fi…