首页 > 其他分享 >静态区间查询(条件动态)——ST表

静态区间查询(条件动态)——ST表

时间:2024-01-24 10:35:54浏览次数:23  
标签:rt 静态 查询 lt 给出 数组 条件 区间 ST

目录

问题引入

给出一个长度为n的数组a,并且给出m咨询问,每次询问给出边间lt和rt,要求给出lt和rt之间的最大值

思路一览

  1. 暴力法:记录数组,对于每一次询问,就从lt到rt遍历一遍
  2. ST:对数组的区间做一个倍增处理,将每一个区间的答案记录下来,最后使用区间进行比较找出答案

具体分析

假设我们开一个数组,为f[i][j]表示数组中从下标为i的点往后2j位的区间的答案(包括该点),比如f[1][0]就是第一位往后一位的答案,那么其实f[1][0]就是a[1],f[1][1]就是max(a[1], a[2]),其实也就是max(f[1][0], f[2][0]),由此我们可以大胆猜测一下f数组是否是一个可以递推的关系,简单的画出下面的图

现在我们要求f[i][3],那么我们可以从已经求过的区间即f[i][2]和f[i+4][2]求出,观察关系,其实f[i+4][2] = f[22][2],也就是说,我们可以从小区间向高区间推,我们刚开始的条件就是f[n]0
那么该递推式的退出条件是什么呢,假设 现在正在求点i,那么该区间的重点就是end = i+(1<<j)-1,当end <= n时,那么该区间可以正常计算,当end > n时,有两种情况,一种是数组越界报错,另外一种是额外的数组默认值会对答案进行影响,因此,该递推式结束的条件应该是end <= n即i+(1<<j)-1 <= n,由此,我们可以写出以下的预处理代码

for(int i=1; i<=n; i++) cin >> f[i][0];
for(int j=1; j<=20; j++) {
  //j的取值上限大致就是log2(n)级别
  for(int i=1; i+(1<<j)-1<=n; j++) f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
}

以上是预处理过程,当我们要查询的时候,只有两个边界条件lt和rt,据此我们可以求出区间长度和区间级别,k=log2((rt-lt+1)),不妨假设lt=2,rt=9,因此它的区间级别应该是3,即从2开始向后查8个,j=3,但是这是刚刚好的情况,当这个区间大一点,比如是[2, 10],这样的话就会漏查,因此在从区间右边查一遍,起点就是rt-(1<<k)+1,由此我们写出以下的查询代码

int k = log2(rt-lt+1);
int ans = max(f[lt][k], f[rt-(1<<k)+1][k]);

正常的查询大致就是这样,这里给出洛谷P2880以及又臭又长Code

条件动态?

上面说的都是静态查询,至于标题中的条件动态就是来源于洛谷P1198这个题目的提醒,条件是什么呢,该题目给出的条件是只往数组的末尾加元素,这样的话就会只影响到idx-(1<<j)+1的数,其中idx为数组的末尾指针,只需要列举区间即可(对于一个特定的区间,需要修改的也只有一个点),也就是更新该点的该区间值即可,那么按照这个说法,其实往头插应该也是可以的,往头插的话就是只需要更改头结点的值即可,但是比较麻烦的就是它的遍历问题,但是往中间插就是肯定不行了,因为往中间插的话f数组就需要时时更新了,代价太大,不如树状数组出马,这里给出上面一题的Code

标签:rt,静态,查询,lt,给出,数组,条件,区间,ST
From: https://www.cnblogs.com/notalking569/p/17984049

相关文章

  • Visual Studio 中预置的代码片段
    代码片段功能可用位置#if创建 #if 指令和 #endif 指令。任何位置。#region创建 #region 指令和 #endregion 指令。任何位置。~创建包含类的终结期(析构函数)。在类中。attribute为派生自 Attribute 的类创建声明。在命名空间(包括全局命名空间)、......
  • WebStorm 没有找到本地修改记录LocalChanges,怎么查看本地修改记录
    一直用IDEA做后端Java开发,也写过vue+elementUI的前端代码,但前后端都放在一个项目里写,本地修改代码记录,可以在git-LocalChanges中查看修改记录。 最近前后端分离,自己需要单独用WebStorm写前端项目代码,在git里就找不到本地修改记录了,如下图:File-->Setting-->VersionControl......
  • STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驱动
    1、准备材料开发板(正点原子stm32f407探索者开发板V2.4)STM32CubeMX软件(Version6.10.0)野火DAP仿真器keilµVision5IDE(MDK-Arm)ST-LINK/V2驱动XCOMV2.6串口助手2、实验目标使用STM32CubeMX软件配置STM32F407开发板的FSMC实现以轮询或DMA的方式读写IS62WV51216(SRAM)芯片3、......
  • 数仓如何递归查询视图依赖
    本文分享自华为云社区《GaussDB(DWS)如何递归查询视图依赖》,作者:半岛里有个小铁盒。1.前言适用版本:【8.1.0(及以上)】本文通过介绍withrecursive递归查询的办法来实现查询视图的层级依赖关系2.实现简介对于postgres生态来说,视图的依赖关系没有现成的查询方法,需要对系统表pg......
  • 强大的Stream API
    StreamAPI说明 Java8中有两大最为重要的改变。第一个是Lambda表达式;另外一个则是StreamAPI。 StreamAPI(java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为StreamAPI可以极大提供Java程序员的生产力,让程序员写出高效率......
  • java8找出两个集合List<Employee> 中 id相同的元素,再将别的属性合并,放在新的集合里面
    可以使用Java8的StreamAPI来实现这个需求。具体步骤如下:1.创建一个新的集合,用于存放合并后的元素。2.使用Stream的filter()方法过滤出id相同的元素。3.使用Stream的map()方法将id相同的元素合并成一个新的元素,其中别的属性可以通过自定义的合并规则来实现。4.使用Stream的c......
  • Registry&Harbor私有仓库构建
    一、介绍Harbor是一个用于存储Docker镜像的企业级Registry服务。Registry是Dcoker官方的一个私有仓库镜像,可以将本地的镜像打标签进行标记然后push到以Registry起的容器的私有仓库中。企业可以根据自己的需求,使用Dokcerfile生成自己的镜像,并推到私有仓库中,这样可以大大提高拉取......
  • 内部类(匿名、成员、静态)
    1、匿名内部类匿名内部类在方法中创建,不能用public等来修饰在方法内部使用,此时,只需要声明一个Outer05对象,然后使用f1方法,就可以使用这个匿名内部类 类的匿名内部类,如果去掉大括号中的内容,则变成创建一个Father对象,但是有这个大括号,则是使用一个匿名内部类,如果类本身不是......
  • Operation system note
    KeywordsContextSwitchTime  bigparts: CommunicationbetweenaDeviceandtheCPU •MethodOne:PollingorHand-shaking•MethodTwo:Interrupts•MethodThree:DMA–DirectMemoryAccess  MemoryManagementAmemorymanagementunitorMMU......
  • 44从零开始用Rust编写nginx,命令行参数的设计与解析及说明
    wmproxywmproxy已用Rust实现http/https代理,socks5代理,反向代理,静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子项目地址国内:https://gitee.com/tickbh/wmproxygithub:https://github.com/......