數列區間最大值(ST表)

Jerrycyx發表於2024-08-05

預處理部分

\[\max(a[i,i+2^k-1]) =\max \left\{ \begin{aligned} \max&(a[i,i+2^{k-1}-1])\\ \max&(a[i+2^{k-1},i+2^{k-1}+2^{k-1}-1]) \end{aligned} \right.= \left\{ \begin{aligned} \max&(a[i,i+2^{k-1}-1])\\ \max&(a[i+2^{k-1},i+2^k-1]) \end{aligned} \right.= \max(a[i,i+2^k-1]) \]

查詢部分

\[p=\lfloor \log_{2}{(l+r-1)} \rfloor \]

\[\max(a[l,r]) = \max \left\{ \begin{aligned} \max&(a[l,l^p-1])\\ \max&(a[r-2^p+1,r-2^p+1+2^p-1]) \end{aligned} \right. = \max \left\{ \begin{aligned} \max&(a[l,l^p-1])\\ \max&(a[r-2^p+1,r]) \end{aligned} \right. \]

程式碼

#include<cstdio>
#define max(x,y) (x)>(y)?(x):(y)
using namespace std;

inline int read()
{
	int x=0;bool w=true;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=false;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^'0');ch=getchar();}
	return w?x:-x;
}

const int N=1e5+5,Q=1e6+5;
int n,q;

int lg2[N],f[N][25];
inline void ST_Init()
{
	for(int i=2;i<=n;i++)
		lg2[i]=lg2[i>>1]+1;
	for(int k=1;k<=lg2[n];k++)
		for(int i=1;i+(1<<k)-1<=n;i++)
			f[i][k]=max(f[i][k-1],f[i+(1<<k-1)][k-1]);
	//max(a[i,i+2^k-1])=max(max(a[i,i+2^(k-1)-1]),max(a[i+2^(k-1),i+2^(k-1)+2^(k-1)-1=i+2^k-1]))
	return;
}
inline int ST_query(const int l,const int r)
{
	int p=lg2[r-l+1];
	return max(f[l][p],f[r-(1<<p)+1][p]);
}

int main()
{
	n=read(),q=read();
	for(int i=1;i<=n;i++)
		f[i][0]=read();
	ST_Init();
	for(int i=1;i<=q;i++)
	{
		int x=read(),y=read();
		printf("%d\n",ST_query(x,y)); 
	}
	return 0;
}

相關文章