版权声明:QAQ https://blog.csdn.net/priesty_/article/details/82938700
1.ST算法
解决RMQ[区间最值问题]的强力工具√;
即 Sparse Table 算法,时间复杂度为O(nlogn)预处理+O(1)查询;
预处理使用 DP 的思想,f(i, j)表示区间中的最小值,即 f[i,j]表示从第 i 个数起连续 个数中的最小值
假设要查询从m到n这一段的最小值, 那么我们先求出一个最大的k, 使得k满足2^k<=(n-m+1),于是我们就可以把[m, n]分成两个(部分重叠的)长度为的区间.
至于为什么查询时左端点是,
因为我们需要找到一个点x,使得
这样的话就可以得到;
蓝后类推另外一个√
模板用的洛谷的p3685
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<deque>
#include<cmath>
#include<cctype>
#define LL long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=1000000+5;
int n,m;
int dp[maxn][20+1];
int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
int query(int l,int r)
{
int k=log(r-l+1)/log(2);
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)dp[i][0]=read();
for(int j=1;j<=21;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
dp[i][j]=max(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
}
for(int i=1;i<=m;i++)
{
int l=read(),r=read();
printf("%d\n",query(l,r));
}
return 0;
}