[蓝桥杯学习] ST表

RMQ问题

[蓝桥杯学习] ST表_第1张图片

ST 表

[蓝桥杯学习] ST表_第2张图片

用状态 s[i][j] 记录区间长度为 2^j 的长度的区间的最大值

所以状态转移方程就是 st[i][j] = max( st[i][j-1] , st[i+(1 << (j-1))][j-1] )

注意状态转移的方向,保证区间合法性(i+2^j  不能超过数组大小)

写完这些后,定义好第一个,就可以从前往后进行计算

用ST表进行区间查询

[蓝桥杯学习] ST表_第3张图片

ST表存储的区间是2的整数倍,所以要计算的是,如何从要求的区间,到ST表存储的区域。

要寻找一个k,如果满足以下的大小关系,

[蓝桥杯学习] ST表_第4张图片

就可以取两个区间的最大值 max(st[l][k],st[r-(1<

[蓝桥杯学习] ST表_第5张图片

k值的具体计算是,把(r-l+1)对2求对数,并向下取整,可以用强制类型转换来实现。

求区间最大值的代码

#include 
#include 
#include 
using namespace std;

#define ll long long

const int N = 5e5 + 5;
int n,q;
ll a[N];
ll st[N][21];

ll getMax(int l,int r)
{
  //计算k,区间长度对2取对数
  int k = log(r-l+1)/log(2);
  return max(st[l][k],st[r-(1<> n >> q;
  for(int i = 1 ; i <= n ; i++)
  {
    int x;
    cin >> x;
    a[i] = x;
  }
  //构造ST表
  //1.初始化
  for(int i = 1 ; i <= n ; i++) st[i][0] = a[i];
  //2.利用状态转移方程求ST表
  for(int j = 1 ; j <= 20 ; j++)
  {
    for(int i = 1 ; i <= n ; i++)
    {
      if(i + (1<> l >> r;
    cout << getMax(l,r) <<'\n';
  }



  return 0;
}

你可能感兴趣的:(蓝桥杯,学习)