rmq_ST算法
ST算法: 为离线算法,查询最值问题
minn[i][j]表示区间 [i , i+(1<<j)-1] 的最小值,minn[i][j]一定是偶数个数的最小值,所以对它一分为二
状态方程:minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1])
查询[l,r]区间时,区间个数是r-l+1, k为log2(r-l+1),那么最小值为minn[l][k],
因为log2(r-l+1)可能存在一点误差,即判断一下后端点
即min(minn[l][k],minn[r-(1<<k)+1][r])
最大值:
同理
代码如下:
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int N=1e5+7; int minn[N][21],maxx[N][21],n; int Log2[N];//表示log2(i) void ST() { for(int i = 0; i <= n; i ++)Log2[i] = (i == 0 ? -1 : Log2[i >> 1] + 1); for(int j=1;j<21;j++) for(int i=1;i+(1<<j)<=n+1;i++) { minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]); maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]); } } int query_min(int l,int r) { int k=Log2[r-l+1]; return min(minn[l][k],minn[r-(1<<k)+1][k]); } int query_max(int l,int r) { int k=Log2[r-l+1]; return max(maxx[l][k],maxx[r-(1<<k)+1][k]); } int main() { int q; scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&minn[i][0]); maxx[i][0]=minn[i][0]; } ST(); while(q--) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query_max(l,r)-query_min(l,r)); } return 0; }