st表、树状数组与线段树 笔记与思路整理

已更新(2/3):st表、树状数组

 

st表、树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题。


 

一、ST表(Sparse Table

st表预处理时间复杂度O(n log n),查询O(1),但不支持在线更改,否则要重新进行预处理。

使用一个二维数组:st[i][j]存储i为起点,长度为2j的一段区间最值,即arr[i, i + 2j - 1]。

具体步骤(以最小值为例):

  1. 将st[i][0]赋值为arr[i];
  2. 利用动态规划思想,dp出st[i][j] = min(st[i][j - 1], st[i + 2j - 1][j - 1])  (1 ≤ i ≤ n, 1 ≤ j ≤ log2 n);
  3. 查询时,定义len为log2(r - l + 1),区间[l, r]的最小值为min(st[l][len],st[r - 2len + 1][len])。

总时间复杂度为O(n log n + q),q为请求数。

代码实现(两个st表分别求最大最小值):

#include <bits/stdc++.h>
using namespace std;
int stmin[60010][20], stmax[60010][20];
int n, q, arr[60010], minans, maxans;
void init(){
    for(int j = 1 ; j <= n ; j++)stmax[j][0]=stmin[j][0]=arr[j];
    for(int i = 1 ; i <= log2(n) ; i++){
        for(int j = 1  ; j <= n ; j++){
            stmax[j][i] = stmax[j][i-1];
            if(j + (1 << (i-1)) <= n ) stmax[j][i] = max(stmax[j][i], stmax[j+(1<<(i-1))][i-1]);
            stmin[j][i] = stmin[j][i-1];
            if(j + (1 << (i-1)) <= n ) stmin[j][i] = min(stmin[j][i], stmin[j+(1<<(i-1))][i-1]);
        }
    }
}
void query(int l,int r){
    int len = log2(r - l + 1);
    minans = min(stmin[l][len],stmin[r - (1 << len) + 1][len]);
    maxans = max(stmax[l][len],stmax[r - (1 << len) + 1][len]);
}
int main(){
    scanf("%d %d", &n, &q);
    for(int i = 1 ; i <= n  ; i++)
        scanf("%d", &arr[i]);
    init();
    int l,r;
    for(int i = 1 ; i <= q ; i++ ){
        scanf("%d %d", &l, &r);
        query(l, r);
        printf("%d %d\n", minans, maxans);
    }
    return 0;
}
View Code

相关文章:

  • 2021-10-19
  • 2021-10-09
  • 2022-12-23
  • 2022-12-23
  • 2021-08-17
  • 2021-07-13
  • 2021-09-11
  • 2022-12-23
猜你喜欢
  • 2021-10-05
  • 2021-09-04
  • 2021-07-31
  • 2022-12-23
  • 2023-01-06
  • 2021-09-06
  • 2021-04-11
相关资源
相似解决方案