首页 > 编程语言 >C++ 算法学习——1.8 倍增与ST表

C++ 算法学习——1.8 倍增与ST表

时间:2024-10-11 13:23:10浏览次数:3  
标签:arr int 1.8 C++ 查询 ST 区间 st 预处理

在 C++ 中,"倍增"(也称为"指数增长"或"指数级别增长")是一种算法优化技术,它通常用于解决一些需要频繁查询某个区间内的信息的问题,例如在处理动态规划、搜索等算法中。倍增思想的主要目的是通过预处理和存储一些中间结果,以加速后续的查询操作。

具体来说,倍增思想通常包括以下步骤:

  1. 预处理阶段:在预处理阶段,计算和存储一些中间结果,通常是按指数级别递增的步长。这些中间结果可以是某个位置到其 2^k(k 为整数)步后的位置的信息。

  2. 查询阶段:在查询阶段,通过利用预处理阶段的中间结果,可以快速获取到所需的信息,而不必每次都进行全面的计算。

倍增思想的优点在于它通过空间换时间的方式来提高查询效率,尤其在需要频繁查询某个区间内信息的情况下,可以显著减少计算量。

ST表(Sparse Table)是一种用于高效处理区间查询问题的数据结构,常用于解决静态数组的区间查询问题,如区间最值。ST表的主要思想是预处理出一个二维数组,使得对于任意区间 [l, r],可以在 O(1) 的时间复杂度内得到其区间查询结果。

在C++算法中,ST表的实现为以下步骤:

  1. 预处理阶段:构建一个二维数组 st[][],其中 st[i][j] 表示从下标 i 开始、长度为 2^j 的区间内的最值(或其他查询结果)。
  2. 预处理阶段时间复杂度为 O(nlogn),其中 n 表示数组的长度。
  3. 查询阶段:对于区间查询 [l, r],可以通过 st[l][k]st[r-2^k+1][k] 的最值(或其他查询结果)来快速获得该区间的查询结果,其中 k 是满足 2^k <= r - l + 1 的最大整数。

预处理代码(最大值为例)示例:

void buildST(int n) {
    for (int i = 0; i < n; i++) {
        st[i][0] = arr[i];
    }

    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 0; i + (1 << j) <= n; i++) {
            st[i][j] = max(st[i][j-1], st[i + (1 << (j-1))][j-1]);
        }
    }
}

预处理原理:首先默认最大值st[i][0]对应的当前i的位置最大值就是自己。 然后更新每个在n范围内的(i,j)对应的st[i][j]的值,用上述式子,具体可以比划感受一下为什么是这样的式子。此时是按两个两个,四个四个,八个八个的方式在更新st数组。

 查询代码(最大值)示例:

int query(int l, int r) {
    int k = log2(r - l + 1);
    return max(st[l][k], st[r - (1 << k) + 1][k]);
}

这里详细解释一下查询代码的原理:

  1. 预处理阶段(buildST 函数)中,我们构建了一个二维数组 st,其中 st[i][j] 表示从位置 i 开始、长度为 2^j 的区间内的最大值。

  2. query 函数中,我们首先计算区间的长度 r - l + 1,然后使用 log2 函数找到一个整数 k,使得 2^k 是不大于区间长度的最大的2的幂次方。这个 k 值对应了我们在预处理阶段建立的 st 数组的列索引。

  3. 接着,我们通过 st[l][k]st[r - (1 << k) + 1][k] 来找到区间 [l, r] 中的最大值。这里的 (1 << k) 表达式实际上就是 2^k,它代表了以 l 为起点、长度为 2^k 的区间的左半部分,而 r - (1 << k) + 1 表示了以 r 为终点、长度为 2^k 的区间的右半部分。

  4. 通过比较这两个区间的最大值,我们可以得到区间 [l, r] 中的真正最大值。

以下是完整的示例代码:

#include <iostream>
#include <cmath>

using namespace std;

const int MAXN = 100005;
const int LOGMAXN = 20; // log2(MAXN) + 1
int *arr;
int **st;

void buildST(int n) {
    for (int i = 0; i < n; i++) {
        st[i][0] = arr[i];
    }

    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 0; i + (1 << j) <= n; i++) {
            st[i][j] = max(st[i][j-1], st[i + (1 << (j-1))][j-1]);
        }
    }
}

int query(int l, int r) {
    int k = log2(r - l + 1);
    return max(st[l][k], st[r - (1 << k) + 1][k]);
}

int main() {
    int n;
    cout << "Enter the number of elements: ";
    cin >> n;

    arr = new int[n];
    st = new int*[n];
    for (int i = 0; i < n; i++) {
        st[i] = new int[LOGMAXN];
    }

    cout << "Enter " << n << " elements: ";
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    buildST(n);

    cout << "Built ST table for array:" << endl;
    for (int i = 0; i < n; i++) {
        for (int j = 0; (1 << j) <= n; j++) {
            cout << st[i][j] << " ";
        }
        cout << endl;
    }

    int l, r;
    cout << "Enter the range [l, r] for query: ";
    cin >> l >> r;
    cout << "Maximum value in range [" << l << ", " << r << "] is: " << query(l, r) << endl;

    delete[] arr;
    for (int i = 0; i < n; i++) {
        delete[] st[i];
    }
    delete[] st;

    return 0;
}

P1. 洛谷p2880Balanced lineup G 

#include <iostream>
#include <cmath>

using namespace std;

const int MAXN = 100005;
const int LOGMAXN = 20; // log2(MAXN) + 1
int *arr;
int **st;
int **stmin;

void buildST(int n) {
    for (int i = 0; i < n; i++) {
        st[i][0] = arr[i];
        stmin[i][0]=arr[i];
    }

    for (int j = 1; (1 << j) <= n; j++) {
        for (int i = 0; i + (1 << j) <= n; i++) {
            st[i][j] = max(st[i][j-1], st[i + (1 << (j-1))][j-1]);
            stmin[i][j] = min(stmin[i][j-1], stmin[i + (1 << (j-1))][j-1]);
        }
    }
}

int query(int l, int r) {
    int k = log2(r - l + 1);
    return max(st[l][k], st[r - (1 << k) + 1][k])-min(stmin[l][k], stmin[r - (1 << k) + 1][k]);
}

int main() {
    int n;cin >> n;
    int q;cin>>q;
    arr = new int[n];
    st = new int*[n];
    stmin = new int*[n];
    for (int i = 0; i < n; i++) {
        st[i] = new int[LOGMAXN];
        stmin[i] = new int[LOGMAXN];
    }

    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }

    buildST(n);
    for(int i=1;i<=q;i++)
    {
        int l, r;
        cin >> l >> r;
        cout <<query(l-1, r-1) << endl;//题目是1作为索引开头
    }
    return 0;
}

标签:arr,int,1.8,C++,查询,ST,区间,st,预处理
From: https://blog.csdn.net/William_Edmund/article/details/142848784

相关文章

  • C++ 算法学习——1.8 单调队列算法
    单调队列(MonotonicQueue)是一种特殊类型的队列,通常用于解决一些数组或序列相关的问题。和单调栈类似,单调队列也具有一些特定的性质,在解决一些问题时非常有用。以下是关于单调队列的一些重要点:定义:单调队列是一种数据结构,队列中的元素满足单调递增或单调递减的性质。应用:单......
  • 一款Java CMS 网站管理系统,基于RuoYi-fast二次开发,网站后台采用SpringBoot + MyBati
    一款JavaCMS网站管理系统基于RuoYi-fast二次开发,网站后台采用SpringBoot+MyBatis文章目录前言一、开源地址二、环境要求三、功能亮点3.1扩展功能3.2内置功能四、安装方法4.1、拉取源码4.2、修改数据库链接配置4.3、创建数据库并导入数据4.4、配置资源上传......
  • Stylized Far East 古代国风建筑城镇宫殿场景模型
    下载:​​Unity资源商店链接资源下载链接效果图:......
  • 基于STM32设计自动输液监测系统(241)
    文章目录一、前言1.1项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成1.2设计思路1.3项目开发背景【1】选题的意义【2】参考文献【3】项目背景【4】摘要【5】设计的主要内容和功能1.4开发工具的选择1.5系统功能总结1.6......
  • 基于STM32的智慧超市管理设计与实现(239)
    文章目录一、前言1.1项目背景1.2设计思路1.3功能详细总结【1】环境监测与智能控制【2】商品管理与顾客服务【3】实时数据展示1.4环境监测页面设计1.5超市收银上位机1.6系统框架图1.7硬件原理图1.8硬件实物二、硬件选型2.1STM32开发......
  • github 上将 stable 合并到 master 分支步骤
    本地仓库分支:origin远端仓库分支:upstream切到非master分支上,比如dev#本地操作gitbranch-Dmastergitfetchupstreammaster::mastergitcheckoutmaster#这步是拉取远端stable到master上,可能会出错误#fatal:Notpossibletofast-forward,abortinggitpu......
  • Android Studio添加依赖 新版 和 旧版 的添加方式(Gradle添加依赖)(Java)
    旧版的(在线添加)1找文件在项目的build.gradle文件中添加依赖(在下面的节点中添加库格式’组:名字:版本号‘)dependencies{implementation'com.example:library:1.0.0'}implementation‘组:名字:版本号’添加完成之后上方会出现如下图提示(点击现在同步)(Sy......
  • 不要慌,FastGPT 告诉我这是技术性调整,利好大 A!
    一觉醒来,股市又变天了,到处一片哀嚎,我看了下前几天牛市的赚钱名单,咱们公众号的粉丝没有一个在里面,说实话很失望,希望大家多做些有意义的事情,而不是整天虚度光阴。一个个平时看着都挺厉害,也没赚到钱,我很失望。你们什么时候才能起飞?我都替你们着急如果你对自己的技术没有绝对的自信......
  • Chromium 前端form表单提交过程分析c++
    一、本文以一个简单的HTML表单,包含两个文本输入框和一个提交按钮:<formaction="demo_form.php">Firstname:<inputtype="text"name="fname"><br>Lastname:<inputtype="text"name="lname"><br><i......
  • 【软件教程OBS下载使用】一篇文章教会你如何下载安装使用OBS-Studio
    OBSStudio是全新的OBS(OpenBroadcasterSoftware),是一款广泛应用的视频直播录制软件,跟经典版的区别就是,音频分路简单,在不出错的情况下性能优于经典版。可以说是高级版,目前仍然处于初期阶段,比起经典版,错误修复频繁,对于插件的兼容性情况不如经典版,错误修复频繁,对于插件的兼容......