当前位置: 首页 > news >正文

线段树模板

文章目录

  • 线段树
      • 练习题目
      • 线段树概念
      • 区间维护
        • 辅助函数
        • 创建线段树 :build
        • 修改线段树 :modify
        • 查询线段树:query
      • 全部代码

线段树

练习题目

洛谷题单
【模板】线段树 1
【模板】线段树 2
开关
扶苏的问题

线段树概念

线段树是一种高级数据结构,与树状数组一样,被用来处理区间查询,修改问题,并且线段树的最大优点是对动态数据的处理十分高效。

来看看线段树能处理的问题:

  • 求区间的修改。给你一个区间,让你查询区间的左节点 , 右节点和增加量。如果用普通的数组,加上m次询问,则时间复杂度将会达到接近O(mn)阶,是非常低效的。
  • 区间和问题,查询,修改区间的元素,求和等等。使用普通数组对指定的区间求和,加之m次询问,则时间复杂度也会达到O(mn),也可以使用前缀和求区间和,但是前缀和虽然高效,但是远没有线段树灵活,线段树能够处理的问题是非常多的。
  • 线段树对于以上两种问题求解都具有O(mlogn)的时间复杂度,是非常高效的。

线段树是具有以下形态的二叉树,其中树上的每个节点都是一个线段区间 。

看图可以发现线段树的几个特征:

这颗二叉树是采用分治法来划分区间,并且构建子树的,左右子树各一半。

这颗二叉树的每个节点都是一个线段区间,非叶子节点的线段区间是一段不相等的区间,叶子节点的线段区间的只包含一个元素。

区间维护

求区间维护是线段树最常用的使用方法之一,一共有五类函数:

  • 辅助函数(前置准备,上移与下移): update ,pushdown
  • 创建线段树 :build
  • 修改线段树 :modify
  • 查询线段树 :query
  • 更新线段树 :update
辅助函数
inline void update(int root)
{node[root].sum = node[root * 2].sum + node[root * 2 + 1].sum;//将左子树和右子树的值合并
}inline void pushdown(int root)
{int lazy = node[root].lazy;node[root * 2].lazy += lazy;node[root * 2].sum += (node[root * 2].r - node[root * 2].l + 1) * lazy;//下发懒惰标记node[root * 2 + 1].lazy += lazy;node[root * 2 + 1].sum += (node[root * 2 + 1].r - node[root * 2 + 1].l + 1) * lazy;//下发懒惰标记node[root].lazy = 0;//清空懒惰标记
}
创建线段树 :build
void build_tree(int root, int l, int r)
{node[root].l = l;//封装左区间node[root].r = r;//封装右区间if (l == r){node[root].sum = a[l];//大小与需要相同,就赋值return;}int mid = (l + r) >> 1;build_tree(root * 2, l, mid);//递归左子树build_tree(root * 2 + 1, mid + 1, r);//递归右子树update(root);//合并左右子树
}
修改线段树 :modify
void modify(int root, int l, int r, int k)
{if (node[root].l == l && node[root].r == r){node[root].sum += (r - l + 1) * k;//值加上区间内增加的值node[root].lazy += k;//懒惰标记return;}pushdown(root);//下发懒惰标记,因为接下来要访问左右子树int mid = (node[root].l + node[root].r) >> 1;//取中间节点if (r <= mid){modify(root * 2, l, r, k);//全在左边的情况,递归左子树}else if (l > mid)全在右边的情况,递归右子树{modify(root * 2 + 1, l, r, k);}else//负责左右都递归{modify(root * 2, l, mid, k);modify(root * 2 + 1, mid + 1, r, k);}update(root);//因为修改了左右子树,所以要合并左右子树return;
}
查询线段树:query
long long query(int root, int l, int r)
{if (node[root].l == l && node[root].r == r){return node[root].sum;//如果区间正好吻合,则返回原值}pushdown(root);//下发懒惰标记,因为接下来要访问左右子树int mid = (node[root].l + node[root].r) >> 1;if (r <= mid)//同modify中的递归{return query(root * 2, l, r);}else if (l > mid){return query(root * 2 + 1, l, r);}return query(root * 2, l, mid) + query(root * 2 + 1, mid + 1, r);//这里要返回和
}

全部代码

#include <bits/stdc++.h>
using namespace std;struct tree
{int l, r;long long sum, lazy;
} node[300010];int n, m;
int a[100010];inline void update(int root)
{node[root].sum = node[root * 2].sum + node[root * 2 + 1].sum;//将左子树和右子树的值合并
}inline void pushdown(int root)
{int lazy = node[root].lazy;node[root * 2].lazy += lazy;node[root * 2].sum += (node[root * 2].r - node[root * 2].l + 1) * lazy;//下发懒惰标记node[root * 2 + 1].lazy += lazy;node[root * 2 + 1].sum += (node[root * 2 + 1].r - node[root * 2 + 1].l + 1) * lazy;//下发懒惰标记node[root].lazy = 0;//清空懒惰标记
}
void build_tree(int root, int l, int r)
{node[root].l = l;//封装左区间node[root].r = r;//封装右区间if (l == r){node[root].sum = a[l];//大小与需要相同,就赋值return;}int mid = (l + r) >> 1;build_tree(root * 2, l, mid);//递归左子树build_tree(root * 2 + 1, mid + 1, r);//递归右子树update(root);//合并左右子树
}void modify(int root, int l, int r, int k)
{if (node[root].l == l && node[root].r == r){node[root].sum += (r - l + 1) * k;//值加上区间内增加的值node[root].lazy += k;//懒惰标记return;}pushdown(root);//下发懒惰标记,因为接下来要访问左右子树int mid = (node[root].l + node[root].r) >> 1;//取中间节点if (r <= mid){modify(root * 2, l, r, k);//全在左边的情况,递归左子树}else if (l > mid)全在右边的情况,递归右子树{modify(root * 2 + 1, l, r, k);}else//负责左右都递归{modify(root * 2, l, mid, k);modify(root * 2 + 1, mid + 1, r, k);}update(root);//因为修改了左右子树,所以要合并左右子树return;
}long long query(int root, int l, int r)
{if (node[root].l == l && node[root].r == r){return node[root].sum;//如果区间正好吻合,则返回原值}pushdown(root);//下发懒惰标记,因为接下来要访问左右子树int mid = (node[root].l + node[root].r) >> 1;if (r <= mid)//同modify中的递归{return query(root * 2, l, r);}else if (l > mid){return query(root * 2 + 1, l, r);}return query(root * 2, l, mid) + query(root * 2 + 1, mid + 1, r);//这里要返回和
}
int main()
{cin >> n >> m;for (int i = 1; i <= n; i++){cin >> a[i];}build_tree(1, 1, n);//建树while (m--){long long op, x, y, k;cin >> op >> x >> y;if (op == 1){cin >> k;modify(1, x, y, k);//区间修改}else if (op == 2){cout << query(1, x, y) << endl;//区间查询}}return 0;
}

相关文章:

线段树模板

文章目录 线段树练习题目线段树概念区间维护辅助函数创建线段树 &#xff1a;build修改线段树 &#xff1a;modify查询线段树&#xff1a;query 全部代码 线段树 练习题目 洛谷题单 【模板】线段树 1 【模板】线段树 2 开关 扶苏的问题 线段树概念 线段树是一种高级数据结构&a…...

【TypeScript】知识点梳理(三)

#void前面提到了代表空&#xff0c;但有个特殊情况&#xff0c;是空不是空&#xff0c;细谈是取舍&#xff0c;但我们不深究hhh# 代码示例&#xff1a; type func () > voidconst f1: func function() {return true; } 定义了空&#xff0c;返回非空值&#xff0c;理论…...

题解:SP1741 TETRIS3D - Tetris 3D

这是一道二维线段树&#xff08;树套树&#xff09;标记永久化的模版题 前置知识点&#xff08;来自董晓算法&#xff09; 好&#xff0c;现在开始我们的分析&#xff1a; 题意简述&#xff1a; 在一个二维平面内&#xff0c;有给定的坐标&#xff0c;在这个坐标范围内加上…...

EWSTM8 IAR for STM8 软件分享

1. 软件简介 EWSTM8&#xff0c;即 IAR for STM8&#xff0c;全称为 IAR Embedded Workbench for STM8&#xff0c;它是 IAR ARM 嵌入式工作台之一&#xff0c;用于开发 STM8。IAR 有多个不同名的版本&#xff0c;对应不同的开发对象。 EWSTM8最新版本为V3.11&#xff08;202…...

非机动车检测数据集 4类 5500张 电动三轮自行车 voc yolo

非机动车检测数据集 4类 5500张 电动三轮自行车 voc yolo 非机动车检测数据集介绍 数据集名称 非机动车检测数据集 (Non-Motorized Vehicle Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型&#xff08;包括YOLOv5、YOLOv6、YOLOv7等&#x…...

Chromium 中JavaScript FileReader API接口c++代码实现

FileReader 备注&#xff1a; 此特性在 Web Worker 中可用。 FileReader 接口允许 Web 应用程序异步读取存储在用户计算机上的文件&#xff08;或原始数据缓冲区&#xff09;的内容&#xff0c;使用 File 或 Blob 对象指定要读取的文件或数据。 文件对象可以从用户使用 <…...

k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载

目录 1 MetailLB 搭建 1.1 MetalLB 的作用和原理 1.2 MetalLB功能 1.3 部署 MetalLB 1.3.1 创建deployment控制器和创建一个服务 1.3.2 下载MealLB清单文件 1.3.3 使用 docker 对镜像进行拉取 1.3.4 将镜像上传至私人仓库 1.3.5 将官方仓库地址修改为本地私人地址 1.3.6 运行清…...

南昌网站建设让你的企业网站更具竞争力

南昌网站建设让你的企业网站更具竞争力 在当今竞争激烈的市场环境中&#xff0c;一个高质量的网站不仅是企业形象的展示平台&#xff0c;更是吸引客户、提升业绩的重要工具。南昌作为江西的省会城市&#xff0c;互联网产业的蓬勃发展为企业网站建设提供了良好的机遇。 首先&am…...

【重学 MySQL】五十三、MySQL数据类型概述和字符集设置

【重学 MySQL】五十三、MySQL数据类型概述和字符集设置 MySQL数据类型概述MySQL字符集设置注意事项 MySQL数据类型概述 MySQL是一个流行的关系型数据库管理系统&#xff0c;它支持多种数据类型&#xff0c;以满足不同数据处理和存储的需求。理解并正确使用这些数据类型对于提高…...

《计算机原理与系统结构》学习系列——计算机的算数运算(上)

系列文章目录 目录 ALU行波进位加法器超前进位加法器整数运算加减法乘法无符号数相乘N位乘法数的工作流程N位乘法器改进&#xff1a;硬件资源更快速的乘法 MIPS中的乘法除法 32位除法器流程除法器改进 更快速的除法 MIPS中的除法总结 ALU ALU功能&#xff1a;对a&#xff0c;…...

如何在华为云服务器查看IP地址,及修改服务器登录密码!!!

1.在华为云服务器查看IP地址 (1).第一步&#xff1a; 先找到控制台 (2).第二步&#xff1a; 点击华为云Flexus云服务 (3)第三步&#xff1a; 找到公网IP&#xff0c;就找到华为云服务器IP地址啦。 注意&#xff1a;在操作以上步骤的前提是要已注册华为云账号及购买云服务器…...

JAVA并发编程高级——JDK 新增的原子操作类 LongAdder

LongAdder 简单介绍 前面讲过,AtomicLong通过CAS提供了非阻塞的原子性操作,相比使用阻塞算法的同步器来说它的性能已经很好了,但是JDK开发组并不满足于此。使用AtomicLong 时,在高并发下大量线程会同时去竞争更新同一个原子变量,但是由于同时只有一个线程的CAS操作会成功,…...

常见的基础系统

权限管理系统支付系统搜索系统报表系统API网关系统待定。。。 Java 优质开源系统设计项目 来源&#xff1a;Java 优质开源系统设计项目 | JavaGuide 备注&#xff1a;github和gitee上可以搜索到相关项目...

在 window 系统下安装 Ubuntu (虚拟机)

文章目录 零、Ubuntu 和 Vmware workstation 资源一、下载 Ubuntu二、下载 Vmware Workstation Pro三、安装 Vmware Workstation Pro四、创建虚拟机五、配置 Ubuntu 零、Ubuntu 和 Vmware workstation 资源 如果觉得自己下载 Ubuntu 和 Vmware workstation 麻烦&#xff0c;也…...

鸿蒙开发(NEXT/API 12)【访问控制应用权限管控概述】程序访问控制

默认情况下&#xff0c;应用只能访问有限的系统资源。但某些情况下&#xff0c;应用存在扩展功能的诉求&#xff0c;需要访问额外的系统数据&#xff08;包括用户个人数据&#xff09;和功能&#xff0c;系统也必须以明确的方式对外提供接口来共享其数据或功能。 系统通过访问…...

(10)MATLAB莱斯(Rician)衰落信道仿真1

文章目录 前言一、莱斯分布随机变量二、仿真代码与结果1.仿真代码2.仿真结果画图 后续 前言 首先给出莱斯衰落信道模型&#xff0c;引入了莱斯因子K&#xff0c;并给出莱斯分布的概率密度函数公式。然后导出莱斯分布随机变量的仿真表示式&#xff0c;建立MATLAB仿真代码&#…...

什么是重卡充电桩?

有什么广告&#xff1f;没有广告&#xff0c;纯纯的介绍。 在政策与市场双重驱动下&#xff0c;充电桩市场已经开启加速模式&#xff0c;行业的火苗越烧越旺。同时&#xff0c;随着新能源重卡的广泛普及&#xff0c;重卡充电桩也迎来了新的发展机遇。 此种背景下 &#xff0c…...

模拟实现消息队列(基于SpringBoot实现)

提要&#xff1a;此处的消息队列是仿照RabbitMQ实现&#xff08;参数之类的&#xff09;&#xff0c;实现一些基本的操作&#xff1a;创建/销毁交互机&#xff08;exchangeDeclare&#xff0c;exchangeDelete&#xff09;&#xff0c;队列&#xff08;queueDeclare&#xff0c;…...

C语言:预编译过程的剖析

目录 一.预定义符号和#define定义常量 二.#define定义宏 三.宏和函数的对比 四、#和##运算符 五、条件编译 在之前&#xff0c;我们已经介绍了.c文件在运行的过程图解&#xff0c;大的方面要经过两个方面。 一、翻译环境 1.预处理&#xff08;预编译&#xff09; 2.编译 3…...

算法——单调栈

单调栈&#xff1a; 保持栈内的元素始终递增或递减。 单调递增 待处理数组{1,5,2,5,7,2,8} public void sameyIncrease(int[] nums) {Stack<Integer> stack new Stack<>();for(int i 0; i < nums.length; i) {//当栈空的时候可以直接进栈或者要进栈的数大于…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

DBLP数据库是什么?

DBLP&#xff08;Digital Bibliography & Library Project&#xff09;Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高&#xff0c;数据库文献更新速度很快&#xff0c;很好地反映了国际计算机科学学术研…...