ST表是离线算法,在O(nlogn)的时间复杂度内预处理后可以在O(1)的时间内查询[l,r]的最值
ST表的思路是用动态规划的思路预处理以第i个数为起点,长度为2^j的区间的最值;
dp方程为
区间最大值
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int inf=0x3f3f3f3f;
int t;
int n,m,k;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;i++)
cin>>a[i];
m=(int)((double)log(n)/log(2.0))+1;
vector<vector<int>> st(n+1,vector<int>(m,-inf)); //最大值
for(int j=0;j<m;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
if(!j)
st[i][j]=a[i];
else
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);//最大值
function<int(int,int)> getmax = [&] (int l,int r)
{
int kk=(int)((double)log(r - l + 1)/log(2.0));
return max(st[l][kk],st[r-(1<<kk)+1][kk]);//最大值
};
int q;
cin>>q;
while(q--)
{
int l,r,k;
cin>>l>>r;
cout<<getmax(l,r)<<endl;//最大值
}
return 0;
}
区间最小值
/*
author:wuzx
*/
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int inf=0x3f3f3f3f;
int t;
int n,m,k;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
vector<int> a(n+1);
for(int i=1;i<=n;i++)
cin>>a[i];
m=(int)((double)log(n)/log(2.0))+1;
vector<vector<int>> st(n+1,vector<int>(m,inf)); //最小值
for(int j=0;j<m;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
if(!j)
st[i][j]=a[i];
else
st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);//最小值
function<int(int,int)> getmin = [&] (int l,int r)
{
int kk = (int)((double)log(r - l + 1)/log(2.0));
return min(st[l][kk],st[r-(1<<kk)+1][kk]);//最小值
};
int q;
cin>>q;
while(q--)
{
int l,r,k;
cin>>l>>r;
cout<<getmin(l,r)<<endl;//最小值
}
return 0;
}
ST表还可以结合其他离线数据结构如差分