ST表
ST表是用来维护RMQ的.
主要利用了倍增的思想,令f[i][j]表示从i开始向后2^j长度的RMQ值。
转移时由前一半和后一半进行转移:f[i][j]=max/min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
然后查询[l,r]的时候:
我们来考虑一下:记k=log2(r-l+1)。k为log2(区间长度)再下取整。所以从l向后扩展(1<<k)长,从r向前扩展(1<<k)长。
设从r向前扩展(1<<k)长的位置为x,则x+(1<<k)-1=r -> x=r-(1<<k)+1。
然后return max/min(f[l][k],f[r-(1<<k)+1][k])就好了。
模板代码(最大值):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <queue> #define ll long long #define space putchar(' ') #define endl putchar('\n') #define debug puts("------------------------") #define F(i,x,n) for(int i=x;i<=n;++i) #define F_(i,x,n) for(int i=x;i>=n;--i) using namespace std; inline void read(int &a) {a=0;int c=getchar(),b=1; while(c>'9'||c<'0') {if(c=='-')b=-1;c=getchar();} while(c>='0'&&c<='9') a=(a<<3)+(a<<1)+c-48,c=getchar();a*=b; } inline int Rem() {int a=0,c=getchar(),b=1; while(c>'9'||c<'0') {if(c=='-')b=-1;c=getchar();} while(c>='0'&&c<='9') a=(a<<3)+(a<<1)+c-48,c=getchar();return a*=b; } inline void write(int x) {if(x>9)write(x/10);putchar('0'+x%10);} inline void W(int x) {if(x<0){putchar('-'),x=-x;}write(x);} /**/ const int N=1e5+5; int f[N][21]; int n,m; /**/ int query(int l,int r) { int len=log2(r-l+1); return max(f[l][len],f[r-(1<<len)+1][len]); } int main() { // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); read(n);read(m); for(int i=1;i<=n;i++) read(f[i][0]); for(int j=1;j<=20;j++) { for(int i=1;i+(1<<j)-1<=n;i++) { f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } for(int i=1,l,r;i<=m;i++) { read(l);read(r); cout<<query(l,r)<<'\n'; } }
注意一下不要再傻逼的把log2(r-l+1)写成log(r-l+1)了。。。