高级数据结构—线段树(一)

学线段树的原因是因为cf的一道题目始终想不出来怎么优化,后来知道区间查询和修改要用到线段树。。。

原题:Iva & Pav

线段树的作用

  1. 区间最值查询:可以高效地找到给定区间内的最大值、最小值等。

  2. 区间和查询:可以高效地计算给定区间内元素的和、积等。

  3. 区间更新:可以高效地对给定区间内的元素进行更新操作,如增加一个固定值、赋值等。

  4. 区间覆盖:可以将给定区间内的元素全部赋值为一个固定值。

  5. 区间合并:可以将多个区间合并成一个区间,快速地进行区间合并操作。

  6. 区间离散化:可以将区间内的元素进行离散化处理,方便进行查询和统计操作。

  7. 区间交集:可以快速地找到多个区间之间的交集

线段树和树状数组的区别 

 刚学完树状数组来学线段树,一开始还不知道他们具体的差别在哪里,那么以下是我的理解。

1.树状数组是前缀和优化,要用到前缀和的时候较为方便。

2.树状数组用来进行单点修改,区间查询;或者区间修改,单点查询较为方便,而区间查询和区间修改较为复杂,因此可以用线段树优化。

3.线段树适用于需要频繁的区间查询和更新操作的问题,如区间最值、区间和等,能够灵活处理各种区间操作。

4.树状数组适用于一维数组的前缀和查询和更新操作,对于简单的区间操作也能够提供高效的解决方案。

例题: 

最大数

题目链接:最大数

直接看代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
//单点插入,区间查询
const int N = 2e5+5;
struct node{int l,r;int v;
}tr[N*4];int m,p;//子节点的信息更新父节点
void pushup(int u){tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
}//u为当前线段树节点编号
void build(int u,int l,int r){tr[u]={l,r};if(l==r)return;int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);
}//查询以u为根节点,区间[l,r]中的最大值
int query(int u, int l, int r) {//      Tl-----Tr//   L-------------R   //1.不必分治,直接返回if(tr[u].l >= l && tr[u].r <= r) return tr[u].v;int mid = tr[u].l + tr[u].r >> 1;int v = 0;//     Tl----m----Tr//        L-------------R //2.需要在tr的左区间[Tl, m]继续分治if(l <= mid) v = query(u << 1, l, r);//     Tl----m----Tr//   L---------R //3.需要在tr的右区间(m, Tr]继续分治if(r > mid) v = max(v, query(u << 1 | 1, l, r));//     Tl----m----Tr//        L-----R //2.3涵盖了这种情况return v;
}//u为节点编号,x为修改位置,v为修改的值
void modify(int u,int x,int v){if(tr[u].l==tr[u].r)tr[u].v=v;//叶子节点,递归出口else{int mid=tr[u].l+tr[u].r>>1;//分治,修改位置偏左往左边遍历,偏右往右边遍历if(x<=mid)modify(u<<1,x,v);else {modify(u<<1|1,x,v);}pushup(u);//回溯,子节点的信息更新父节点}
}signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//n表示树中节点个数,last表示上一次查询的结果int n=0,last=0;cin>>m>>p;//初始化线段树,节点的区间最多为[1,m]build(1,1,m);while(m--){char op;cin>>op;if(op=='A'){//添加节点int t;cin>>t;//在n+1处插入modify(1,n+1,(t+last)%p);//节点个数+1n++;}else {int l;cin>>l;//查询[n - L + 1, n]内的最大值,u = 1,即从根节点开始查询last=query(1,n-l+1,n);cout<<last<<"\n";}}return 0;
}

你能回答这些问题吗

题目链接:你能回答这些问题吗

如图:

如图,假设我们要求区间的最大子段和,有三种情况:

1.包含所有左半边,部分右半边----->左半边的区间和+右半边的前缀和

2.包含所有右半边,部分左半边----->右半边的区间和+左半边的后缀和

3.中间的一部分----->左半边的后缀和+右半边的前缀和

因此我们的结构体要记录四个信息:

struct node{int l,r;int sum;//[l,r]的区间和int lmax;//最大前缀和int rmax;//最大后缀和int tmax;//区间[l,r]最大连续子段和
}tr[N*4];

 同时pushup函数根据上图可以推出:(重载函数)

//u表示该节点,l表示该节点的左子树,r表示该节点的右子树
void pushup(node &u,node &l,node &r){u.sum=l.sum+r.sum;//三种最大连续子段和的情况u.lmax=max(l.lmax,l.sum+r.lmax);u.rmax=max(r.rmax,r.sum+l.rmax);u.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax});
}void pushup(int u){pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}

代码附上:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e5+5;
int w[N];
int n,m;
struct node{int l,r;int sum;//[l,r]的区间和int lmax;//最大前缀和int rmax;//最大后缀和int tmax;//区间[l,r]最大连续子段和
}tr[N*4];//u表示该节点,l表示该节点的左子树,r表示该节点的右子树
void pushup(node &u,node &l,node &r){u.sum=l.sum+r.sum;//三种最大连续子段和的情况u.lmax=max(l.lmax,l.sum+r.lmax);u.rmax=max(r.rmax,r.sum+l.rmax);u.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax});
}void pushup(int u){pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}void build(int u,int l,int r){if(l==r)tr[u]={l,r,w[r],w[r],w[r],w[r]};//找到叶子节点else{tr[u]={l,r};//设当前区间为[l,r]int mid=l+r>>1;build(u<<1,l,mid);//左子树build(u<<1|1,mid+1,r);//右子树pushup(u);//修改父节点}
}//每次从1号节点开始找,找到位置位于x的数,并把它修改为v
void modify(int u,int x,int v){if(tr[u].l==x && tr[u].r==x)tr[u]={x,x,v,v,v,v};else{int mid=tr[u].l+tr[u].r>>1;if(x<=mid)modify(u<<1,x,v);//x位于当前区间的左半子区间else modify(u<<1|1,x,v);//x位于当前区间的右半子区间pushup(u);//修改父节点的相关信息}
}node query(int u,int l,int r){if(tr[u].l>=l&&tr[u].r<=r)return tr[u];//被包含else{int mid=tr[u].l+tr[u].r>>1;if(r<=mid)return query(u<<1,l,r);//查询左半区间else if(l>mid)return query(u<<1|1,l,r);//查询右半区间else{//横跨左右区间auto left=query(u<<1,l,r);auto right=query(u<<1|1,l,r);node res;pushup(res,left,right);return res;}}
}signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++)cin>>w[i];build(1,1,n);//建树int k,x,y;while(m--){cin>>k>>x>>y;if(k==1){//查询if(x>y)swap(x,y);cout<<query(1,x,y).tmax<<"\n";}else modify(1,x,y);//修改}return 0;
}

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

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

相关文章

关于MCU核心板的一些常见问题

BGA植球与焊接&#xff08;多涂焊油&#xff09;&#xff1a; 【BGA芯片是真麻烦&#xff0c;主要是植锡珠太麻烦了&#xff0c;拆一次就得重新植】https://www.bilibili.com/video/BV1vW4y1w7oNvd_source3cc3c07b09206097d0d8b0aefdf07958 / NC电容一般有两种含义&#xff1…

Python爱心代码

爱心效果图&#xff1a; 完整代码&#xff1a; import random from math import sin, cos, pi, log from tkinter import *# 定义画布尺寸和颜色 CANVAS_WIDTH 640 CANVAS_HEIGHT 480 CANVAS_CENTER_X CANVAS_WIDTH / 2 CANVAS_CENTER_Y CANVAS_HEIGHT / 2 IMAGE_ENLARG…

AI容器化部署开发尝试 (一)(Pycharm连接docker,并部署django测试)

目标&#xff1a;使用容器化技术快速部署AI应用进行开发。 注意&#xff1a;从 Docker 19.03 开始&#xff0c;Docker 引入了对 NVIDIA GPU 的原生支持&#xff0c;因此若AI要调用GPU算力的话docker版本也是有要求的&#xff0c;后面博客测试。 当然本篇博客还没设计到GPU的调…

微服务两种方式登录

目录 1.restTemplate方式 1.1页面 1.2消费者 1.3生产者 1.4效果 2.Feign方式 2.1Service 2.2生产者 三个生产者 一个消费者&#xff0c;三个生产者需要用mysqlmybatis 三个不同的数据库。 页面输入用户名和密码&#xff0c;提交到后端消费者&#xff0c;消费者传到生产…

vLLM-prefix浅析(System Prompt,大模型推理加速)

原文&#xff1a;vLLM-prefix浅析&#xff08;System Prompt&#xff0c;大模型推理加速&#xff09; 简介 本文浅析了在大模型推理加速方面一个非常优秀的项目 vLLM 的一个新特性 Prefix。在 Prompt 中有相同前缀时可以提高吞吐量降低延迟&#xff0c;换句话说可以省去这部分…

【C++】:构造函数和析构函数

目录 前言一&#xff0c;构造函数1.1 什么是构造函数1.2 构造函数的特性1.3 总结 二&#xff0c;析构函数2.1 什么是析构函数2.2 析构函数的特性2.3 总结 前言 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何…

JVM学习笔记(五)内存模型

目录 1、原子性 1.1 问题分析 1.2 解决方法 2、可见性 2.1 退不出的循环 2.2 解决办法 3、有序性 3.1 诡异的结果 3.2 解决办法 3.3 有序性理解 3.4 happens-before 4、CAS与原子类 4.1 CAS 4.2 乐观锁与悲观锁 4.3 原子操作类 5、synchronized 优化 5.1 轻量…

华为认证云计算前景如何

互联网/移动互联网经历了高速发展的二十年&#xff0c;我们有幸一起见证了华为、阿里、腾讯、百度、字节跳动、京东、滴滴、拼多多等互联网公司的崛起&#xff0c;让普通技术人实现逆袭拿到高薪&#xff0c;也让小镇做题家们有了阶层跨越的机会。 但机会都是留给有准备的人&…

记录一个hive中因没启yarn导致的spark引擎跑insert语句的报错

【背景说明】 刚在hive中配置了Spark引擎&#xff0c;在进行Hive on Spark测试时报错&#xff0c; 报错截图如下&#xff1a; [atguiguhadoop102 conf]$ hive which: no hbase in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/opt/module/jdk1.8.0_212/bin:/opt/mod…

分享三个转换速度快、准确率高的视频转文字工具

想要直接将视频转换成文字&#xff0c;转换工具很重要&#xff01;给大家分享三个转换速度快、准确率高的视频转文字工具&#xff0c;轻松完成转换。 1.网易见外 https://sight.youdao.com/ 网易家的智能转写翻译服务工作站&#xff0c;网页端就可以直接使用&#xff0c;支持视…

【threejs教程7】threejs聚光灯、摄影机灯和汽车运动效果

【图片完整效果代码位于文章末】 在上一篇文章中我们实现了汽车模型的加载&#xff0c;这篇文章主要讲如何让汽车看起来像在运动。同时列出聚光灯和摄像机灯光的加载方法。 查看上一篇&#x1f449;【threejs教程6】threejs加载glb模型文件&#xff08;小米su7&#xff09;&…

Web3钱包开发获取测试币-Base Sepolia(二)

Web3钱包开发获取测试币-Base Sepolia(二) 基于上篇 Web3钱包开发获取测试币-Polygon Mumbai(一) &#xff1a;https://suwu150.blog.csdn.net/article/details/137949473 我们今天来说说Base Sepolia网络的添加。 一、添加Base Sepolia到钱包 什么是Base Sepolia&#xff1f…

如何在PostgreSQL中使用索引覆盖扫描提高查询性能?

文章目录 解决方案1. 创建合适的索引2. 确保查询能够使用索引覆盖扫描3. 调整查询以利用索引覆盖扫描4. 监控和调优 示例代码1. 创建索引2. 编写查询3. 检查是否使用索引覆盖扫描4. 调整索引 总结 在PostgreSQL中&#xff0c;索引是提高查询性能的关键工具之一。索引允许数据库…

【Hello算法】 > 第 3 关 >栈与队列

数据结构 之 数组与链表 1 栈 / 栈的常见操作、实现、应用2 队列 /队列的常见操作、实现、应用3 双向队列4 Tips ———————————————————————————————————————————————————————————- ————————————————…

LeetCode in Python 48. Rotate Image/Matrix (旋转图像/矩阵)

旋转图像/矩阵的重点是寻找旋转前后对应位置的坐标关系。 示例&#xff1a; 图1 旋转图像/矩阵的输入输出示意图 代码&#xff1a; class Solution:def rotate(self, matrix):n len(matrix)for i in range(n // 2):for j in range(i, n - 1 - i):topleft matrix[i][j]ma…

Navicat连接SQLSever报错:[08001] MicrosoftTCP Provider 远程主机强迫关闭了一个现有的连接

Navicat连接SQLSever报错&#xff1a;[08001] [Microsoft][SQL Server Native Client 10.0]TCP Provider: 远程主机强迫关闭了一个现有的连接 问题分析 旧版的MSSQL 如果不是最新版的&#xff0c;可以去这安装以下即可。 最新版的MSSQL 如果是安装最新版的MSSQL连接不上很正…

鸿蒙OpenHarmony【轻量系统 环境搭建】 (基于Hi3861开发板)

安装Hi3861开发板特有环境 除上述[安装库和工具集]和[安装编译工具]外&#xff0c;针对Hi3861开发板还需要安装特定的编译工具。 工具要求 表1 Hi3861 WLAN模组需要安装的编译工具 开发工具用途SCons3.0.4编译构建工具python模块&#xff1a;setuptools、kconfiglib、pycry…

Macs Fan Control Pro for Mac:全面优化Mac风扇控制软件

Macs Fan Control Pro for Mac是一款专为苹果电脑用户设计的风扇控制软件&#xff0c;旨在通过精确的风扇速度调节&#xff0c;全面优化Mac的散热性能&#xff0c;确保系统始终运行在最佳状态。 Macs Fan Control Pro for Mac中文版下载 该软件具备实时监控功能&#xff0c;能够…

java 词法分析练习

import parser.Parser;import java.util.ArrayList; import java.util.Arrays; import java.util.List;public class Main {public static void main(String[] args) {// 关键词List<String> keyList new ArrayList<>(Arrays.asList("int","String…

利用STM32 HAL库实现USART串口通信,并通过printf重定向输出“Hello World“

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 上一篇使用STM32F407的HAL库只需1行代码实现US…