ST表(倍增表)
介绍 st表 之前先看看 RMQ 问题是什么东西吧
RMQ
RMQ : Range Maximum/minimum Query
顾名思义,这就是指区间最大或最小值(区间最值)
ST表
ST表:Spars Table,一种可以解决 RMQ 的,基于 倍增 的数据结构
令 \(f[i][j]\) 表示从 \(i\) 开始连续 \(2^j\) 个数中的最值,如果 \(i\) 后面的数不足 \(2^j\) 个则全取
转移方程:
\[ f[i][j]=\left\{\begin{aligned}
&min/max(f[i][j-1],f[i+2^{j-1}][j-1])& &,& &j>0,i+2^{j-1}\leq n&\\
&f[i][j-1]& &,& &j>0,i+2^{j-1}>n&\\
&a[i]& &,& &j=0&
\end{aligned}\right.\]
- \(f\) 数组可以递推得到
代码:
int x=log(n)/log(2);
for(int j=1;j<=x;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
时间复杂度: \(O(nlog(n))\)
询问方式:
询问区间为 \([l,r]\) ,设 \(x=\lfloor{log_2(l-r+1)}\rfloor\) ,则区间 \([l,l+2^x-1]\) 和 区间 \([r-2^x+1,r]\) 一定覆盖了 \([l,r]\) 这个区间内所有元素
所以答案为: \(min(f[l][x],f[r-2^x-1][x])\)
小优化:对于 \(1\) ~ \(n\) 每一个数先预处理 \(log(x)\) 下取整的结果,每次讯问时即为 \(O(1)\) 的复杂度
代码:
lg[0]=-1;
for(int i=1;i<=n;i++) lg[i]=lg[i/2]+1;
for(int i=1;i<=m;i++){
int le,r;
scanf("%d%d",&le,&r);
int x=r-le+1;
printf("%d\n",max(f[le][lg[x]],f[r-(1<<lg[x])+1][lg[x]]));
}