区间最值问题-RQM(ST表,线段树)

news2025/7/19 10:10:37

1.ST表求解

ST表的实质其实是动态规划,下面是区间最小的递归公式,最大只需将min改成max即可

f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);

二维数组的f[i][j]表示从i开始连续2*j个数的最小/大值。

例如:我们给出一个数组a[10]={0,1,2,4,6,7,9,2,12,3};

我们可以给f[i][0]....f[n][0]先初始化为上面数组的值,我们将f[i][j]分为两端,一段是i到i+2^(j-1)-1为一段,i+2^(j-1)到i+2^j-1,f[i][j]就是分出来的这两个段的最大/小值。

于是有了递归公式。

写一道例题

P1816 忠诚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<set>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define TEST1 int T;cin>>T;while(T--)
#define TEST2 int T;T=1;while(T--)
#define lowbit(x) x&(-x) 
#define ll long long
using namespace std;
const int N = 100010;
const int M = 20;
int base1 = 131, base2 = 13311;
int p1 = 1e9 + 7, p2 = 1e9 + 9;
const ll mod = 1e9 + 7;
int n, a[N], f[N][M],m[N][M];
//创建ST表
void create() {
    //初始状态
    //f[i][0]表示从i开始长度为2^0的区间最值为a[i]本身
    for(int i = 1; i <= n; i ++) f[i][0] = a[i],m[i][0]=a[i];
    int k = log2(n);
    //枚举区间长度指数j
    for(int j = 1; j <= k; j ++)
        for(int i = 1; i + (1 << j) - 1 <= n; i ++)
        {
			f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
			m[i][j] = min(m[i][j - 1], m[i + (1 << j - 1)][j - 1]);
		}
            
}
//利用ST表查询区间[L,R]的最大值
int query1(int L, int R) {
	
    int k = log2(R - L + 1);
    return max(f[L][k], f[R - (1 << k) + 1][k]);
}
int query2(int L,int R)
{

	int k=log2(R-L+1);
	return min(m[L][k], m[R - (1 << k) + 1][k]);
}
int main()
{
    int m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) scanf("%d", a + i);
    create();
    while(m --) {
        int L, R;
        scanf("%d%d", &L, &R);
        printf("%d ", query2(L,R));
        
    }
}

其实就是区间最小值。

2.线段树

线段树其实也就是相当于区间分段,(a,b)的左孩子区间就是(a,(a+b)/2)和右孩子((a+b)/2+1,b),(a.b)区间的最值就是他分出的两个区间的最值的最值。

对于上道例题的代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<set>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define TEST1 int T;cin>>T;while(T--)
#define TEST2 int T;T=1;while(T--)
#define lowbit(x) x&(-x) 
#define ll long long
using namespace std;
const int N = 2000010;
const int M = 1e9+2;
int base1 = 131, base2 = 13311;
int p1 = 1e9 + 7, p2 = 1e9 + 9;
const ll mod = 1e9 + 7;
ll n, m, a[N];
struct Node
{
	int l, r, minn = mod;
}tree[N];
void build(int i, int l, int r)
{
	tree[i] = { l,r };
	if (l == r)
	{
		tree[i].minn = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(i << 1, l, mid);
	build(i << 1 | 1, mid + 1, r);
	tree[i].minn = min(tree[i << 1].minn, tree[i << 1 | 1].minn);
}
int ask(int i, int l, int r)
{
	if (l == tree[i].l && r == tree[i].r) return tree[i].minn;
	int mid = tree[i].l + tree[i].r >> 1;
	if (r <= mid) return ask(i << 1, l, r);
	if (l > mid) return ask(i << 1 | 1, l, r);
	return min(ask(i << 1, l, mid), ask(i << 1 | 1, mid + 1, r));
}
void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i];
	build(1, 1, n);
	for (int i = 1; i <= m; i++)
	{
		int l, r;
		cin >> l >> r;
		cout << ask(1, l, r) << " ";
	}
}
int main()
{
	TEST2
	solve();
	return 0;
}

3.其他例题

1.奶牛排队

1274. 奶牛排队 - AcWing题库

区间最大值与最小值的差

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<set>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define TEST1 int T;cin>>T;while(T--)
#define TEST2 int T;T=1;while(T--)
#define lowbit(x) x&(-x) 
#define ll long long
using namespace std;
const int N = 100010;
const int M = 20;
int base1 = 131, base2 = 13311;
int p1 = 1e9 + 7, p2 = 1e9 + 9;
const ll mod = 1e9 + 7;
int n, a[N], f[N][M],m[N][M];
//创建ST表
void create() {
    //初始状态
    //f[i][0]表示从i开始长度为2^0的区间最值为a[i]本身
    for(int i = 1; i <= n; i ++) f[i][0] = a[i],m[i][0]=a[i];
    int k = log2(n);
    //枚举区间长度指数j
    for(int j = 1; j <= k; j ++)
        for(int i = 1; i + (1 << j) - 1 <= n; i ++)
        {
			f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
			m[i][j] = min(m[i][j - 1], m[i + (1 << j - 1)][j - 1]);
		}
            
}
//利用ST表查询区间[L,R]的最大值
int query1(int L, int R) {
	
    int k = log2(R - L + 1);
    return max(f[L][k], f[R - (1 << k) + 1][k]);
}
int query2(int L,int R)
{

	int k=log2(R-L+1);
	return min(m[L][k], m[R - (1 << k) + 1][k]);
}
int main()
{
    int m;
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) scanf("%d", a + i);
    create();
    while(m --) {
        int L, R;
        scanf("%d%d", &L, &R);
        printf("%d\n", query1(L,R)-query2(L,R));
        
    }
}

2.求m区间内的最小值

P1440 求m区间内的最小值 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<set>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define TEST1 int T;cin>>T;while(T--)
#define TEST2 int T;T=1;while(T--)
#define lowbit(x) x&(-x) 
#define ll long long
using namespace std;
const int N = 2000010;
const int M = 1e9 + 2;
int base1 = 131, base2 = 13311;
int p1 = 1e9 + 7, p2 = 1e9 + 9;
const ll mod = 1e9 + 7;
ll n, m, a[N];
struct Node
{
	ll l, r, minn = mod;
}tree[N];
void build(int i, int l, int r)
{
	tree[i] = { l,r };
	if (l == r)
	{
		tree[i].minn = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(i << 1, l, mid);
	build(i << 1 | 1, mid + 1, r);
	tree[i].minn = min(tree[i << 1].minn, tree[i << 1 | 1].minn);
}
int ask(int i, int l, int r)
{
	if (l == tree[i].l && r == tree[i].r) return tree[i].minn;
	int mid = tree[i].l + tree[i].r >> 1;
	if (r <= mid) return ask(i << 1, l, r);
	if (l > mid) return ask(i << 1 | 1, l, r);
	return min(ask(i << 1, l, mid), ask(i << 1 | 1, mid + 1, r));
}
void solve()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i];
	build(1, 1, n);
	for (int i = 1; i <= n; i++)
	{
		if (i == 1)
		{
			cout << "0\n";
			continue;
		}
		int l=max(1ll,i-m), r=i-1;
		cout << ask(1, l, r) << "\n";
	}
}
int main()
{
	TEST2
		solve();
	return 0;
}

用单调队列更简单。。。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iOS中多个tableView 嵌套滚动特性探索

嵌套滚动的机制 目前的结构是这样的&#xff0c;整个页面是一个大的tableView, Cell 是整个页面的大小&#xff0c;cell 中嵌套了一个tableView 通过测试我们发现滚动的时候&#xff0c;系统的机制是这样的&#xff0c; 我们滑动内部小的tableView, 开始滑动的时候&#xff0c…

【驱动篇】龙芯LS2K0300之ADC驱动

实验目的 由于LS2K0300久久派开发板4.19内核还没有现成可用的ADC驱动&#xff0c;但是龙芯官方的5.10内核已经提供了ADC驱动&#xff0c;想要在4.19内核使用ADC就要参考5.10内核移植驱动&#xff0c;本次实验主要是关于ADC驱动的移植和使用 驱动移植 主要的驱动代码主要有3个…

ASRock Creator系列GPU:为AI推理及多GPU系统打造,采用16针电源接口的Radeon RX 7900系列显卡

ASRock 正在筹备推出专为人工智能推理和多GPU系统设计的AMD GPU——Creator系列显卡。这一系列显卡采用双槽位、吹风式设计&#xff0c;并配备16针电源连接器&#xff0c;首发产品包括基于Navi 31架构的AMD Radeon RX 7900XTX和RX 7900 XT型号。这些原属于WS系列的显卡最初在20…

网络安全设备——防火墙

网络安全设备防火墙是一种用来加强网络之间访问控制的特殊网络互联设备。以下是对防火墙的详细解释&#xff1a; 一、定义与基本概念 定义&#xff1a;防火墙是指设置在不同网络&#xff08;如可信任的企业内部网和不可信的公共网&#xff09;或网络安全域之间的一系列部件的…

力扣双指针算法题目:快乐数

目录 1.题目 2.思路解析 3.代码展示 1.题目 . - 力扣&#xff08;LeetCode&#xff09; 2.思路解析 题目意思是将一个正整数上面的每一位拿出来&#xff0c;然后分别求平方&#xff0c;最后将这些数字的平方求和得到一个数字&#xff0c;如此循环&#xff0c;如果在此循环中…

【Linux】在线求助命令--help,man page , info page

我们知道Linux有很多的命令&#xff0c;那LInux要不要背命令&#xff1f; 答案是背最常用的那些就行了 那有的时候我们想查询一些命令的详细用法该怎么办呢&#xff1f; 这里我给出3种方法 1.--help --help的使用方法很简单啊 要查询的命令 --help 我们看个例子 这里我只…

DoIP-1 简介

1. 概述 DoIP-Diagnostic Over Internet Protocol &#xff0c;基于TCPIP协议族的诊断传输协议 DoIP国际标准定义为ISO 13400&#xff0c;总共由五部分组成&#xff1a;  ISO13400-1DoIP的综述  ISO13400-2DoIP的传输层和网络层服务&#xff08;主体部分&#xff09;  I…

vue-element-admin集成方案如何运行以及代码解读

文章目录 1.vue-admin-admin介绍2.运行方法3.代码解读3.1基础外层文件解读&#xff0c;以及eslint关闭&#xff08;如下图&#xff09;3.2内层src文件分析3.2.1 login流程解析 1.vue-admin-admin介绍 1.1 是一个后台前端解决方案(vueelementui)&#xff0c;内置i18国际化解决方…

Javascript常见数据结构和设计模式

在JavaScript中&#xff0c;常见的数据结构包括两大类&#xff1a;原始数据类型&#xff08;Primitive Types&#xff09;和对象类型&#xff08;Object Types&#xff09;。对象类型又可以进一步细分为多种内置对象、数组、函数等。下面是一些JavaScript中常见的数据结构&…

【PWN · ret2syscall | GoPwn】[2024CISCN · 华中赛区]go_note

一道GoPwn&#xff0c;此外便是ret2syscall的利用。然而过程有不小的曲折&#xff0c;参考 返璞归真 师傅的wp&#xff0c;堪堪完成了复现。复现过程中&#xff0c;师傅也灰常热情回答我菜菜的疑问&#xff0c;感谢&#xff01;2024全国大学生信息安全竞赛&#xff08;ciscn&am…

落日余晖映晚霞

落日余晖映晚霞&#xff0c;立于海滨&#xff0c;望夕阳余晖洒于波光粼粼之上&#xff0c;金光跳跃&#xff0c;若繁星闪烁&#xff0c;耀人心目。 海风轻拂&#xff0c;心境宁静&#xff0c;凡尘俗务皆于此刹那消散&#xff0c;思绪万干&#xff0c;或忆往昔点滴&#xff0c;或…

7.7 洛谷

约瑟夫环 P1145 约瑟夫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) index(indexm-1)%num;if(index>k && index<2*k){a[index]0;num--;}ac代码 #include<bits/stdc.h> using namespace std; typedef long long ll;#define IOS ios::sync_with_stdio(0…

【MySQL】Mysql数据库导入导出sql文件、备份数据库、迁移数据库

本文摘要&#xff1a;本文提出了xxx的实用开发小技巧。 &#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&…

UE C++ 多镜头设置缩放 平移

一.整体思路 首先需要在 想要控制的躯体Pawn上&#xff0c;生成不同相机对应的SpringArm组件。其次是在Controller上&#xff0c;拿到这个Pawn&#xff0c;并在其中设置输入响应&#xff0c;并定义响应事件。响应事件里有指向Pawn的指针&#xff0c;并把Pawn的缩放平移功能进行…

秋招突击——7/4——复习{}——新作{最长公共子序列、编辑距离、买股票最佳时机、跳跃游戏}

文章目录 引言复习新作1143-最长公共子序列个人实现 参考实现编辑距离个人实现参考实现 贪心——买股票的最佳时机个人实现参考实现 贪心——55-跳跃游戏个人实现参考做法 总结 引言 昨天主要是面试&#xff0c;然后剩下的时间都是用来对面试中不会的东西进行查漏补缺&#xff…

通过大众点评进行连锁店铺跟踪(均价、门店数等)、关键词店铺挖掘的思路方法

在做一些城市分析、学术研究分析、商业选址、商业布局分析等数据分析挖掘时&#xff0c;大众点评的数据参考价值非常大&#xff0c;这里提供一种通过大众点评进行连锁店铺跟踪&#xff08;均价、门店数等&#xff09;、关键词店铺挖掘的思路方法。 通过大众点评提供搜索页面&a…

【Qt】Qt概述

目录 一. 什么是Qt 二. Qt的优势 三. Qt的应用场景 四. Qt行业发展方向 一. 什么是Qt Qt是一个跨平台的C图形用户界面应用程序框架&#xff0c;为应用程序开发者提供了建立艺术级图形界面所需的所有功能。 Qt是完全面向对象的&#xff0c;很容易扩展&#xff0c;同时Qt为开发…

MuLan:模仿人类画家的多对象图像生成

在图像生成领域&#xff0c;处理包含多个对象及其空间关系、相对大小、重叠和属性绑定的复杂提示时&#xff0c;现有的文本到图像模型仍面临挑战&#xff1a;当文本提示中包含多个对象&#xff0c;并且这些对象之间存在特定的空间关系时&#xff0c;现有模型往往难以准确地捕捉…

LlamaGen:自回归模型的图像生成革命

LlamaGen&#xff1a;自回归模型的图像生成革命 1. 突破性进展&#xff1a;LlamaGen超越传统扩散模型 在图像生成领域&#xff0c;LlamaGen团队带来了颠覆性创新。由香港大学和字节跳动的研究人员共同开发的这一模型&#xff0c;不仅在技术上超越了传统的扩散模型&#xff0c;…

MySQL8.0在windows下的下载安装及详细使用

下载mysql8.0二进制包 下载地址&#xff1a;MySQL :: Download MySQL Community Server 编辑my.ini配置文件 解压二进制包&#xff0c;新建/编辑my.ini配置文件(如果不存在则新建) [client] #客户端设置&#xff0c;即客户端默认的连接参数 # 设置mysql客户端连接服务端时…