模板笔记 ST表 区间选数k

本题链接:用户登录

题目:

样例:

输入
5 3
1 1 2 2 3
1 2
3 3
1 5

输出
4 6

思路:

.        根据题意,给出数组,以及多个区间,问这些区间中,最小值之和 和 最大值之和,分别是多少。

        由于题目中的数组元素是静态性的,典型的 RMQ 问题,给出元素,以及区间,进行询问即可。当然这里也是可以 使用 线段树进行求解,由于这道题是静态性的,所以我们可以直接使用 ST 表 的数据结构,进行求解即可。

线段树 的方式 是 可以解决动态性的 ,也可以解决静态性的,即线段树可以 边修改元素边询问。

ST 表 的方式 是 对口静态性的, 即 只能询问,不可以修改。

        根据这题,我们 “对症下药” 使用 ST表 方式方便些。

       

        ST 表 ,是 典型的 RMQ 数据结构,采用的是 倍增 思想。

        倍增,顾名思义,就是以2幂的成倍的增长。

        其中的核心思想就是:

        通过记录每一个区间的前半段和后半段,

        达到省略询问 重叠的区间,随后返回这些区间的最值

        ST 表类似 动态规划 dp ,根据 倍增关系得到的公式 i + 2^{^{j}} - 1

        我们假设得到一个区间 中的左端点 l  = i  , 那么 根据 倍增 ,我们右端点   r = i + 2^{^{j}} - 1

        这里  r = i + 2^{^{j}} - 1  中  -1 是维护闭区间。

        

        随后,求这个区间的最值,我们可以截取 前半段 和 后半段的最值记录好对应的区间的最值

 随后当求到我们整个  i 到 i + 2^{^{j}} - 1 的最值的时候

我们 取个 max 或者 min (st(i,i + 2^{^{j - 1}} - 1)  , st(i,i + 2^{^{j - 1}},i + 2^{^{j}} - 1))即可。

这样省略的整个区间的求法,解决重叠部分的求最值。

我们假设 求的区间长度 为 K,则 K = R - L + 1,其中 2的次幂作为我们的截半端点的时候一定是

2^{^{r}} <= K    &&      2^{^{r}} > K / 2  ,所以它们两个不部分有一个极限点重叠,所以我们取max和min两个部分的相应最值,相当于求 区间(L,R) 的最值。

由上图,根据  2^{^{r}} = len(截半长度,右端点) 所以我们取右端点的值就是 r =  log_{2}{len}   。

所以我们要对右端点预处理即可得到各个右端点。

模板函数如下:

const int N = 2e5 + 10;
int v[N],n,q;
int stmin[N][22],stmax[N][22];
inline void Init()
{
	for(int i = 1;i <= n;++i) stmin[i][0] = stmax[i][0] = v[i];
	
	for(int j = 1;j <= log2(n);++j)
	{
		for(int i = 1;i + (1 << j) - 1 <= n;++i)
		{
			int r = i + (1 << j - 1);
			stmin[i][j] = min(stmin[i][j - 1],stmin[r][j - 1]);
			stmax[i][j] = max(stmax[i][j - 1],stmax[r][j - 1]);
		}
	}
}
inline int rmq_min(int L,int R)
{
	int k = log2(R - L + 1);
	int len = (1 << k);
	int r = R - len + 1;
	return min(stmin[L][k],stmin[r][k]);
}
inline int rmq_max(int L,int R)
{
	int k = log2(R - L + 1);
	int len = (1 << k);
	int r = R - len + 1;
	return max(stmax[L][k],stmax[r][k]);
}

代码详解如下:

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define endl '\n'
#include <unordered_map>
#define int long long
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e5 + 10;


// 这是个二维数组 可以理解为 int[][]  其中这个二维数组存储的是 对应的 R  和   r
// 其中 一维 int[] 存储的是 原端点 R      二维 int[][] 存储的是 截半右端点 r 至于为何 r 开 22 ,
// 这个是由于我们 是 log 以 2 为底、长度为基的数值 得到的右端点,所以我们开存在于我们范围内即可
int st_min[N][22],st_max[N][22];
int v[N]; // 存储原数组元素
int n,q;

inline void Init()
{
    // 预处理求出当前点的 右端点 R
    for(int i = 1;i <= n;++i)
    {
        // 这里是 当 左右端点相同的时候 它们的最值等于它们本身
        // 即 : L == R 没有截半,截半端点r = 0
        st_min[i][0] = st_max[i][0] = v[i];
    }

    // 开始求每个截半区间的最值
    for(int R = 1;R <= log2(n);++R) // 这是区间右端点 R
    {
        // 截半区间前提是 截半的右端点 r 区间长度 不超过我们整个数组的区间长度
        for(int L = 1;L + (1 << R) - 1 <= n;++L)
        {
            int r = L + (1 << R - 1); // 截半右端点的 r

            // DP 递推公式   截半区间向右扩展对应的最值,
            // 当前的区间右端点 R 最值  =  (max or min) [之前的截半最值(L, R - 1 ), 现在截半最值(r ,len - 1)]
            // 这样一步一步的递推下去,覆盖重叠部分的区间,记录好对应的截半区间的最值
			st_max[L][R] = max(st_max[L][R - 1],st_max[r][R - 1]); 
            st_min[L][R] = min(st_min[L][R - 1],st_min[r][R - 1]); 
        }
    }
}

inline int rmq_max(int L,int R)
{
    int k = log2(R - L + 1); // 取出对应的截半区间的原右端点
    
    int len = (1 << k);	//截半区间长度
    
    int r = R - len + 1; // 取出对应的截半右端点 r
    
    // 返回这两个截半区间的最值, 等于我们所求的 L ,R 的最值
    return  max(st_max[L][k],st_max[r][k]); 
}

inline int rmq_min(int L,int R)
{
    int k = log2(R - L + 1); // 取出对应的截半区间的原右端点
    
    int len = (1 << k);	//截半区间长度
    
    int r = R - len + 1; // 取出对应的截半右端点 r
    
    // 返回这两个截半区间的最值, 等于我们所求的 L ,R 的最值
    return  min(st_min[L][k],st_min[r][k]); 
}

inline void solve()
{
	cin >> n >> q;
	
	for(int i = 1;i <= n;++i) cin >> v[i];
	
	Init(); // 开始预处理 ST表 初始化
	
	// 存储答案
	int minsum = 0;
	int maxsum = 0;
	
	while(q--)
	{
	int l,r;
	cin >> l >> r;
	
	// 询问累加最值
	minsum += rmq_min(l,r);
	maxsum += rmq_max(l,r);
	
	}
	cout << minsum << ' ' << maxsum << endl;
}

signed main()
{
//	freopen("a.txt", "r", stdin);
	IOS;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CHS_02.2.3.2_1+进程互斥的软件实现方法

CHS_02.2.3.2_1进程互斥的软件实现方法 知识总览如果没有注意进程互斥&#xff1f;单标志法双标志先检查法双标志后检查法Peterson 算法 知识回顾 在这个小节中 我们会学习进程互斥的几种软件实现方法 知识总览 那我们会学习单标志法 双标志 先检查 双标志后检查和Peterson算法…

前端工程化基础(三):Webpack基础

Webpack和打包过程 学习webpack主要是为了了解目前前端开发的整体流程&#xff0c;实际开发中&#xff0c;我们并不需要去手动配置&#xff0c;因为框架的脚手架都已经帮助我们完成了配置 内置模块path 该模块在Webpack中会经常使用 从路径中获取信息 const path require(&qu…

前端Vue v-for 的使用

目录 ​编辑 简介 使用方式 基本使用 v-for"(item, index)中item和index作用 示例 迭代对象 示例 结果 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入…

【Linux】第三十八站:信号处理

文章目录 一、信号处理二、再谈进程地址空间三、内核如何实现信号的捕捉四、sigaction 一、信号处理 我们知道&#xff0c;信号保存以后&#xff0c;会在合适的时候进行处理这个信号。 那么信号是如何被处理的&#xff1f;什么时候进行处理呢&#xff1f; 当我们的进程从内核…

精通Python第13篇—数据之光:Pyecharts旭日图的魔法舞台

文章目录 引言准备工作绘制基本旭日图调整颜色和样式添加交互功能定制标签和标签格式嵌套层级数据高级样式与自定义进阶主题&#xff1a;动态旭日图数据源扩展&#xff1a;外部JSON文件总结 引言 数据可视化在现代编程中扮演着重要的角色&#xff0c;而Pyecharts是Python中一个…

【深度学习每日小知识】Bias 偏差

计算机视觉是人工智能的一个分支&#xff0c;它使机器能够解释和分析视觉信息。然而&#xff0c;与任何人造技术一样&#xff0c;计算机视觉系统很容易受到训练数据产生的偏差的影响。计算机视觉中的偏见可能会导致不公平和歧视性的结果&#xff0c;从而使社会不平等长期存在。…

Python进阶(1) | 使用VScode写单元测试

Python进阶(1) | 单元测试 2024.01.28 VSCode: 1.85.1 Linux(ubuntu 22.04) 文章目录 Python进阶(1) | 单元测试1. 目的2. Python Profile3. 单元测试框架3.1 什么是单元测试3.2 选一个单元测试框架3.3 编写 Python 单元测试代码3.4 在 VSCode 里发现单元测试3.5 再写一个单元…

问题:github上不了,但是其他网页可以正常打开

问题&#xff1a; github上不了&#xff0c;但是其他网页可以正常打开&#xff0c;试了关闭防火墙&#xff0c;dns刷新&#xff0c;都没用后&#xff0c;参考以下文章成功打开Github 1.Github无法访问解决方法 2.github访问不了&#xff1f;详细解决方法 解决办法&#xff1a…

用Python编写的简单双人对战五子棋游戏

本文是使用python创建的一个基于tkinter库的GUI界面&#xff0c;用于实现五子棋游戏。编辑器使用的是spyder&#xff0c;该工具。既方便做数据分析&#xff0c;又可以做小工具开发&#xff0c; 首先&#xff0c;导入tkinter库&#xff1a;import tkinter as tk&#xff0c;这…

leetcode刷题日志-146LRU缓存

思路&#xff1a;使用hashmap储存key&#xff0c;vaule&#xff0c;使用双向链表以快速查到尾结点&#xff08;待逐出的节点&#xff09;&#xff0c;链表的题一定要在纸上画一下&#xff0c;不然连着连着就不知道连在哪里去了 class LRUCache {public class ListNode {int ke…

Java基础常见面试题总结(下)

常见的Exception有哪些&#xff1f; 常见的RuntimeException&#xff1a; ClassCastException //类型转换异常IndexOutOfBoundsException //数组越界异常NullPointerException //空指针ArrayStoreException //数组存储异常NumberFormatException //数字格式化异常ArithmeticE…

【Mac】windows PC用户转用Mac 配置笔记

win转mac使用的一些配置笔记&#xff1b;感觉mac在UI上还是略胜一筹&#xff0c;再配合在win上的操作习惯就体验更好了&#xff0c;对日常办公需求的本人足以。 优化设置 主要 操作优化 AltTab&#xff1a; win 习惯查看全部活动的alt键&#xff0c;对比cmdtab多了可以预览&…

前端——JavaScript

目录 文章目录 前言 一. JavaScript基础 1.JavaScript基本结构 2. JavaScript 执行过程 3. JavaScript 引入方式 二. JavaScript 语法 1.数据类型 2.变量 2.1 var 关键字定义变量 2.2 let 关键字定义变量 2.3 var 与 let 的区别 3.字符串 3.1定义字符串 3.2 字…

Px4学习:进入控制台的方法

运行命令 ls /dev/tty* 会列出所有端口 然后连接飞控通过USB数据线连接到电脑&#xff0c;再运行一次&#xff0c;就可以找到 笔者的是ttyACM0&#xff0c;下面会用到 px4源码 1.13.3 进入控制台 进入PX4源码文件夹&#xff0c;用终端打开&#xff0c;运行命令 ./Tools/mav…

Qt|大小端数据转换

后面打算写Qt关于网络编程的博客&#xff0c;网络编程就绕不开字节流数据传输&#xff0c;字节流数据的传输一般是根据协议来定义对应的报文该如何组包&#xff0c;那这就必然牵扯到了大端字节序和小端字节序的问题了。不清楚的大小端的可以看一下相关资料&#xff1a;大小端模…

jenkins对接K8S

创建连接K8S的凭据 查看需要使用到的命名空间 [rootk8s ~]# kubectl get ns |grep arts-system arts-system Active 16d创建service accounts [rootk8s ~]# kubectl create sa jenkins-k8s -n arts-system serviceaccount/jenkins-k8s created [rootk8s ~]# kubectl…

log4j2 配置入门介绍

配置 将日志请求插入到应用程序代码中需要进行大量的计划和工作。 观察表明&#xff0c;大约4%的代码专门用于日志记录。因此&#xff0c;即使是中等规模的应用程序也会在其代码中嵌入数千条日志记录语句。 考虑到它们的数量&#xff0c;必须管理这些日志语句&#xff0c;而…

CTF CRYPTO 密码学-7

题目名称&#xff1a;敲击 题目描述&#xff1a; 让我们回到最开始的地方 0110011001101100011000010110011101111011011000110110010100110011011001010011010100110000001100100110001100101101001101000011100001100011001110010010110100110100011001000011010100110000…

python简单socket demo

socket说明 socket本质是编程接口(API)&#xff0c;对TCP/IP的封装&#xff0c;TCP/IP也要提供可供程序员做网络开发所用的接口&#xff0c;这就是Socket编程接口。除了常见的http请求之外&#xff0c;一些敏感的数据传输常用socket套接字层直接传输数据。一个简单的domo用于熟…

构造器模式

构造器模式 意图 将一个复杂对象的构建和表示分离&#xff0c;使得相同的构建能创建不同的表示。 解释 案例&#xff1a;想象一个角色扮演游戏的特征生成器。最简单的选择是让计算机为你创建角色。如果你想手动选择特征的细节像职业、性别、头发的颜色等。特征的产生是一个循…