树状数组求区间最大值 (单点修改)

树状数组求区间最大值 讲这个的博文已经不少了,但感觉不够详细不够通俗易懂,所以我尝试着更详细更通俗易懂的说一下我的理解。   这个算法只支持单点修改和区间查询最值。每一次维护和查询的时间复杂度都是O((logn)^2),但这是满打满算的时间复杂度。 假设是要维护和查询区间的最大值(最小值将max改成min 就好了) 这个算法和树状数组维护和查询区间和的方法很相似:   一、数组的含义 1、在维护和查询区间 阅读详情
AI摘要

本文详细介绍了如何使用树状数组求解区间最大值问题,通过调整查询方式,利用lowbit函数特性,实现了从右向左遍历并判断区间是否在目标范围内,最终准确求得指定区间内的最大值。

以前一直把树状数组当作求前缀的工具,但事实上,树状数组是一种分块的方式,因为分块的方式比较独特,所以在求前缀的过程中非常方便;

树状数组的实现原理就不讲了,这里要特别说明的是,lowbit(x) 不仅可以表示区间分块对应存储前缀的位置,同时还能够表示一个区间的长度,这个长度在求区间最大值的时候起到比较重要的左右,也是我之前没想到的部分;

文字说明:

求区间最大值 和 求区间和有很大的不同,因为树状数组求前缀和十分方便,所以通过 sum (R) - sum (L-1) 就能得到一个区间的和;那么区间最大值怎么求?

假设要求  L 到 R 的区间最大值,我们分块仍然是根据lowbit(x) 的方式分,对应分块的最大值也很容易想到,就是求前缀和中累加的部分改成 max () 就行了;

查询: 如果我们根据lowbit 的规则从右向左求区间的最大值,所求的结果是 1 到 R 这个区间的最大值,显然答案可能是不正确的; 我们如何避开  1 到 L-1 这个区间?

我们根据lowbit的规则,从右向左遍历区间块,如果是区间是我们要考虑的范围内就取这个最大值,如果发现当前的区间超出我们要考虑的范围就只取当前区间最末尾的值,然后lowbit - 1,然后继续从右向左遍历,直到所有区间取完为止。

根据上图的步骤,下标为12的这个位置是 9 到 12的最大值,我们能通过lowbit知道当前区间的长度是多少,由此能知道当前区间是不是在我们要考虑的范围内;当遇到下标为8,区间长度大于当前我们要考虑的长度时,我们就只取最末尾的值,也就是对应数组a[8],lowbit - 1 到下标为7这个位置后继续从右向左判断,直到结束。 从图中可以很容易发现,以这种方式遍历,能把所有我们需要考虑的部分都遍历了一遍。

下面这题是求区间最大值的模板题:HDU-1754 

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;
const int Maxn = 2e5+10;

int a[Maxn], h[Maxn], n;  // a[] 数列的值,h[] 区间最大值

void add (int x, int val) {
	while (x <= n) {
		h[x] = max (h[x], val); 
		x += x&(-x);
	}
}

int query (int L, int R) {
	int ret = 0, len = R-L+1;
	while (len && R) {  // len 是当前还需要判断的范围长度,R是对应区间最大值的下标
		if (len < (R&(-R))) {
			ret = max (ret, a[R]);
			R--; len--;
		} else {
			ret = max (ret, h[R]);
			len -= (R&(-R)); // 不断的缩短要判断的区间长度
			R -= (R&(-R)); 
		}
	}
	return ret;
}

int main (void)
{
	int m;
	while (scanf ("%d%d", &n, &m) != EOF) {
		memset (h, 0, sizeof (h));
		for (int i = 1; i <= n; ++i) {
			scanf ("%d", &a[i]);
			add (i, a[i]);
		}
		char op[2], b[10]; int x, y;
		while (m--) {
			scanf ("%s%d%d", op, &x, &y);
			gets (b);
			if (!strcmp (op, "U")) {
				a[x] = y; add (x, y);				
			} else {
				printf ("%d\n", query (x, y));
			}
		}
		
	}
	return 0;
 } 

 

【一百零九】【算法分析与设计】树状数组求解前缀最大值,673. 最长递增子序列的个数,树状数组求前缀区间最大值 树状数组可以求解和前缀区间有关的问题,例如前缀和,前缀区间最值.可以利用logn​的时间复杂度快速查找前缀信息.利用树状数组查询前缀区间中最大值问题.树状数组下标1位置存储arr数组下标1位置的最大值.树状数组2位置存储arr数组1,2位置最大值.数组数组3位置存储arr数组3位置最大值.以此类推…查找arr数组1~i前缀区间最大值.利用lowbit跳转,记录遍历的每一个tree[i]的最大值. 阅读详情

相关推荐

软件测试——白盒测试实验报告,输入年月日算星期几

软件测试——白盒测试实验报告,输入年月日算星期几,测试用例设计和结果展示

weixin_52278161的博客 2746

树状数组求区间最大值(转载)

[数组的含义] 1、在维护和查询区间和的算法中,h[x]中储存的是[x,x-lowbit(x)+1]中每个数的和 . 2、在求区间最值的算法中,h[x]储存的是[x,x-lowbit(x)+1]中每个数的最大值。 求区间最值的算法中还有一个a[i]数组,表示第i个数是多少,也就是原数组。 [单点修改后的更新] 1、在维护区间和的算法中,是这样维护单点修改的 void update(i...

森宝的博客 6505

别再让电池充不满!用CN3791芯片设计太阳能充电电路,这几个调试坑我帮你踩了

本文详细解析了使用CN3791芯片设计太阳能充电电路时的常见调试问题及解决方案。从RCS电阻的选择到MPPT电压偏差的修正,再到线路损耗和温度补偿的优化,提供了全面的避坑指南。通过实测数据和优化方案,帮助工程师提升锂电池充电效率,确保太阳能充电电路的稳定性和可靠性。

weixin_42528191的博客 241

树状数组求区间最值

闲谈一下 树状数组最基本的功能是加速前缀和的更新。 求一个数组的前缀和本来是O(n)的复杂度,用树状数组则为O(nlogn)。 但树状数组优点在于单点更新时复杂度为O(logn),而正常的为O(n),这也就使得树状数组能够进行大规模的更新。 虽然查询速度(O(logn))稍有些慢(相对于O(n)而言),但依旧可以用于大规模的查询。 总之,遇到有不断更新的数组前缀和时可以考虑树状数组。 树状数组求区...

UniverseofHK的博客 5505

linux下wayland协议修改键盘映射

linux下wayland协议,修改键盘映射,实验环境是Ubuntu24,其他wayland协议窗口应该也是可以的。

qq_15027967的博客 1068

AI辅助发明专利撰写实战:30分钟高效生成高质量技术专利文档

在技术专利撰写领域,尤其是软件、算法或系统架构相关的发明专利,如何将创新的技术构思快速、规范地转化为符合《专利法》要求的申请文件,是许多开发者和技术团队面临的共同挑战。传统的人工撰写方式不仅耗时耗力,对撰写人的法律和技术双重背景要求极高,还容易因格式或术语不规范导致审查意见增多。本文将分享一套利用 AI 辅助工具,系统化、高效率地完成一篇高质量发明专利说明书撰写的实战流程。通过清晰的步骤拆解、可复制的提示词(Prompt)工程以及关键注意事项,即使是首次接触专利撰写的开发者,也能在短时间内掌握从技术方案梳理

子夜轻风 957

树状数组之区间最值

树状数组之区间最值 原理 数学原理: 建立树状数组 利用上面的性质,在树状数组的尾部插入数据,来建立一个树状数组 void push(int pos){ int i,lb = lowbit(pos); c[pos] = a[pos]; for(i=1;i<lb;i <<=1){ c[pos] = max(c[pos],c[pos-i]); } } 树的维护 void update(int pos,int v){ i

DC_Fan的博客 1652

AI视频生成技术研究报告:现状、挑战与展望

AI 视频生成技术概述:介绍 AI 视频生成技术的基本概念,回顾其发展历程,从早期依赖图像拼接的简单生成方式,到如今融合多种先进技术的复杂模型应用,梳理技术演进的关键节点和重要突破。同时,分析该技术在当前阶段的特点,包括生成视频的质量、速度、灵活性等方面,以及与传统视频制作方式的差异,阐述 AI 视频生成技术如何改变视频创作的流程和模式。技术实现路径分析。

daqsdfas的博客 4580

树状数组和线段树(蓝桥)

树状数组和线段树 数组数组: 1.用来做单点修改 2.动态求区间和 线段树: 1.树状数组能干的都能干 2.还可以求区间最大值 3.求区间长度 4.有很广的应用 1.动态求连续区间和 题意: 给定 n 个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列 [a,b]的连续和。接下来 m行,每行包含三个整数 k,a,b(k=0,表示求子数列[a,b][a,b]的和;k=1表示第 a 个...

qq_40905284的博客 353

Linux 音频驱动(六) ALSA音频驱动之PCM Write数据传递过程

目录1. 前言2. PCM Data Flow3. 总结 1. 前言 本文,我们将以回放(Playback,播放音频)为例,讲解PCM Data是如何从用户空间到内核空间,最后传递到Codec。 在Linux 音频驱动(一) ASoC音频框架简介中,我们给出了回放(Playback)PCM数据流示意图: 对于Linux来说,由于分为 user space 和kernel space,而且两者之间不能随便互相访问。因此用户如果播放音频,则需要调用copy_from_user()将用户数据从user spa

_Modest_的博客 1万+

Wireshark时间分析实战:精准调试网络延迟与时间同步问题

本文深入探讨了Wireshark在网络延迟与时间同步问题分析中的核心应用。通过实战案例,详细讲解了如何设置时间显示格式、利用时间参考点量化关键路径延迟,以及运用时间平移功能校正错位时间轴。掌握这些时间分析技巧,能帮助网络工程师精准定位隐藏于数据包时序中的性能瓶颈与故障根源。

weixin_29290963的博客 262

树状数组入门及例题题解(三)——区间最值

用树状数组求区间最值 当会用树状数组求区间和了之后 将数组的意义稍微改变 将代码稍作修改 便可以得到用树状数组求区间最值的代码 树状数组入门及例题讲解(一)——区间求和及单点修改 本篇博客对于求区间最值 以求区间最大值为例 读者可以读完之后 尝试写一写求区间最小值的代码 在进行区间求和的代码中 c数组元素 c[i] 代表的是区间中的 第 i-lowbit(i)+1 个元素 到 第 i 个元素的和 ...

i_want_to_studyi的博客 1682

【ODX介绍】-5-用于Flash刷写的ODX-F文件概述

用于Flash刷写的ODX-F文件概述

「汽车电子助手」的博客 2531

树状数组入门及例题讲解(四)——I Hate It

树状数组区间最值入门模板题——I Hate It I Hate It 这是一个简单的树状数组求区间最值的 入门模板题 涉及到了 单点修改 以及求区间最值的操作 熟悉这些函数的书写 就可以轻松的写出这个题 有关 树状数组求区间最值的内容 详见博客: 树状数组入门及例题讲解(三)——区间最值 本题代码如下: #include<cstdio> #include<algorithm&g...

i_want_to_studyi的博客 450

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

2020 8.7 暑期线段树专题

线段树可以在 n*logn 的时间复杂度内实现单点修改、区间 修改、区间查询(区间求和,求区间最大值,求区间最小值) 等操作。 在这里顺便把树状数组附上,树状数组只能区间求和时间复杂度也是n*log n code: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespa...

qq_44797733的博客 147

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

树状数组详解与模版

单点更新 void update(int x,int y,int n){ for(int i=x;i<=n;i+=lowbit(i))//x为更新的位置,y为更新后的数,n为数组最大值 c[i] += y; } 区间查询(1 - x) int getsum(int x){ int ans = 0; ...

weixin_30260399的博客 106

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

树状数组

HDU - 1166敌兵布阵 一个区间,两种操作:区间求和,单点修改。 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; #define maxn 100000 ...

weixin_30794851的博客 56

树状数组与其离散化

树状数组的概念: 树状数组(Fenwick Tree,又称二叉索引树)是一个查询和修改复杂度都为log(n)的数据结构,它是利用二进制的一些特点来实现。它的功能有局限性,主要是用来动态查询连续和(或者是前缀和)的问题。它利用O(n)的附加空间复杂度,将线性的数列结构转化成树状结构从而进行跨越扫描,高效完成查询连续和。 原数组为a[ ],用树状数组储存后的数组为 C[ ] 来一张百度百科里...

一身清贫怎敢入繁华 1514

树状数组基础操作总结

树状数组用于对区间修改和查询频繁的题 树状数组基础操作 1.单点修改+区间查询 转载大佬的说法 模板题 模板代码 #include <bits/stdc++.h> inline int read(){char c = getchar();int x = 0,s = 1; while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();} while(c >= '0' && c <= '9') {x

give it a try 251

hdu 1754 I Hate It (树状数组求区间最大和)(线段树单点修改)

很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。 这让很多学生很反感。 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。 Input 本题目包含多组测试,请处理到文件结束。 在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。 学生ID编号分别从1编到N。 第二行包含N个整数,代表这N个学生的初始成绩,

weixin_44745441的博客 196

线段数区间修改区间查询模板

这几天开始初步学习的树状数组和线段树的内容

2301_80443769的博客 265

第五讲 树状数组和线段树和差分

要点 树状数组包含于线段树,能用树状数组解决的就用,不可以的就用线段树。 树状数组可以快速的求前缀和 给某个位置上的数加上一个数 求某一个前缀和 区域查询,单点修改 第n层:前一层的数加上当前项 … … 第2层:前一层的数加上当前项 第1层:前一层的数加上当前项 第0层:奇数项指向自己 我们可以发现,每一个树状数组的位置保存的都是原数组的一段连续数字的和 如何确定层数呢? 看每一个位置的数的二进制后面有多少个连续的0,就是在第几层。 然后c[x]里面的值等于[x-2k, x] 如何求2k的

北比臼的博客 869

洛谷4315 月下“毛景树”(树链剖分)

传送门 【题目分析】 手残一时爽,代码调一天。。。。。。。。样例都是假的QAQ 与旅游这道题类似,都是权值在路径上,所以将权值赋给深度较深的点,注意查询和更新时不能计算lca。 这道题相当于支持单点修改、区间覆盖、区间加、区间求最大值,常规操作。 【代码~】 #include&lt;bits/stdc++.h&gt; using namespace std; const int MA...

Michael_GLF的博客 270

树状数组和线段树

线段树和树状数组的使用

LivingMu的博客 386
上一篇: 树状数组区间修改+单点查询 (只能单点查询)
下一篇: poj 3468 A Simple Problem with Integers 【区间修改+区间查询(树状数组)】
Y390d
博客等级 码龄9年 11粉丝 165原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值