news 2026/7/30 4:52:59

前缀和,线段树,树状数组,ST表四种数据结构的辨析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前缀和,线段树,树状数组,ST表四种数据结构的辨析

前缀和主要用于解决区间求和,线段数组主要用于动态的区间统计,ST表主要用于查询区间最值,线段树主要用于查询动态的区间最值

主要公式:

pre[i] = pre[i-1] + g[i]; pre[i][j] = g[i][j] - pre[i-1][j-1] + pre[i-1][j] + pre[i][j-1]; S = pre[x2][y2] + pre[x1-1][y1-1] - pre[x1-1][y2] - pre[x2][y1-1];

树状数组主要公式:单体添加,动态范围查询

static int lowbit(int x){ return x & -x; } static void add(int x,int v){ while(x<=n){ tree[x] += v; x += lowbit(x); } } static int sum(int x){ int res = 0; while(x>0){ res += tree[x]; x -= lowbit(x); } return res; }

注:一般范围查询就用sum(r) - sum(l-1);

ST表:主要用于静态范围查询最值,举个模版题

import java.util.*; import java.io.*; public class Main{ static int n; static int [] a; static int [][] st; static int [] log; public static void main(String[] args)throws Exception{ BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer stt = new StringTokenizer(bf.readLine()); n = Integer.parseInt(stt.nextToken()); int m = Integer.parseInt(stt.nextToken()); a = new int [n+1]; st = new int [n+1][20]; log = new int[n+1]; stt = new StringTokenizer(bf.readLine()); for(int i=1;i<=n;i++){ a[i] = Integer.parseInt(stt.nextToken()); st[i][0] = a[i]; } for(int i=2;i<=n;i++){ log[i] = log[i>>1] + 1; } for(int j=1;j<=log[n];j++){ for(int i=1;i+(1<<j)-1<=n;i++){ st[i][j] = Math.max(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } StringBuilder sb = new StringBuilder(); while(m-->0){ stt = new StringTokenizer(bf.readLine()); int L = Integer.parseInt(stt.nextToken()); int R = Integer.parseInt(stt.nextToken()); int k = log[R-L+1]; int ans = Math.max(st[L][k],st[R-(1<<k)+1][k]); sb.append(ans).append("\n"); } System.out.print(sb.toString()); } }

注意两个地方:一个就是固定公式st[i][j] = Math.max(st[i][j-1],st[i+(1<<(j-1))][j-1]);

int ans = Math.max(st[L][k],st[R-(1<<k)+1][k]);

还有就是这题求的是最大值,如果要求最小值的话,把两个max换成min就可以了

离散化:数据很大又很乱时,但是你只关心数据的大小关系,而算法只需要下标时就可以用,举个例子:

import java.io.*; import java.util.*; public class Main { static int n; static int[] h; // 身高(离散化后是排名) static int[] tree; // 树状数组 // lowbit static int lowbit(int x) { return x & -x; } // 树状数组:单点加 1 static void add(int x, int v) { while (x <= n) { tree[x] += v; x += lowbit(x); } } // 树状数组:前缀和 static int sum(int x) { int res = 0; while (x > 0) { res += tree[x]; x -= lowbit(x); } return res; } public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); n = Integer.parseInt(br.readLine()); h = new int[n]; for (int i = 0; i < n; i++) { h[i] = Integer.parseInt(br.readLine()); } // ====================== //离散化 // ====================== int[] b = h.clone(); Arrays.sort(b); // 去重 int m = 0; for (int i = 0; i < n; i++) { if (i == 0 || b[i] != b[i - 1]) { b[m++] = b[i]; } } // 映射为排名(1-based) for (int i = 0; i < n; i++) { h[i] = Arrays.binarySearch(b, 0, m, h[i]) + 1; } // ====================== //树状数组统计逆序对 // ====================== tree = new int[n + 1]; long ans = 0; for (int i = 0; i < n; i++) { int x = h[i]; // 左边比它大的数量 ans += i - sum(x); // 当前元素加入 add(x, 1); } System.out.println(ans); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/21 20:43:35

C盘清理技巧分享

引言C盘空间不足会导致系统卡顿、软件运行异常甚至更新失败。定期清理是维持系统高效运行的关键&#xff0c;需结合基础操作与进阶优化。基础清理方法删除临时文件 通过Windows内置“磁盘清理”工具&#xff08;搜索并运行cleanmgr&#xff09;&#xff0c;勾选“临时文件”“下…

作者头像 李华
网站建设 2026/7/29 17:46:22

WebSocket长连接在LobeChat中的作用解析

WebSocket长连接在LobeChat中的作用解析 在如今的AI对话应用中&#xff0c;用户早已不再满足于“点击发送—等待数秒—整段输出”的机械交互模式。当人们使用像 ChatGPT 这样的智能助手时&#xff0c;真正打动他们的&#xff0c;往往是那一行行仿佛正在思考、逐字浮现的回复——…

作者头像 李华
网站建设 2026/7/30 4:14:27

Netcode for GameObjects Boss Room 多人RPG战斗(1)

L1_项目介绍 概述 Boss Room是一个使用Unity Netcode for GameObjects制作的完整合作多人RPG游戏样本。它展示了典型的多人游戏网络编码模式&#xff0c;旨在帮助开发者学习如何构建类似的多人游戏。 核心特点 支持最多8名玩家合作游戏集成Unity Gaming Services&#xff0…

作者头像 李华
网站建设 2026/7/27 22:08:53

基于显微镜图像的体液细胞分类与异常检测:改进RetinaNet模型实现

1. 基于显微镜图像的体液细胞分类与异常检测&#xff1a;改进RetinaNet模型实现 在医疗诊断领域&#xff0c;体液细胞分析是许多疾病诊断的重要环节。然而&#xff0c;传统的显微镜细胞分析依赖专业医师的经验&#xff0c;耗时且容易受主观因素影响。随着深度学习技术的发展&a…

作者头像 李华