ST表

简介

ST表是一种可进行快速的区间查询的数据结构。他的预处理复杂度为O (nlogn),查询复杂度为O(1)。
ST表能解决可重复贡献问题,即某段区间被重复计算不会影响结果。

实现

初始化

定义状态\(f[i,j]\)表示下标\(i到i+2^j-1\)的数据的结果,共\(2^i\)个元素
转移时可将\(f[i,j]\)分成相等两份\(f[i,j-1]\)\(f[i+2^{j-1},j-1]\)\(f[i,j]\)便从\(f[i,j-1]\)\(f[i+2^{j-1},j-1]\)转移过来
以求区间最大值为例:
\(f[i,j]=max(f[i,j-1],f[i+2^{j-1},j-1])\)

查询

假设要查询区间\([l,r]\)里的最大值,那么我们需要找到恰好能覆盖这一区间的f。设\(k=log_2(r-l+1)\),则区间\([l,r]\)可分为\([l,l+2^k]和[r-2^k+1,r]\)两部分,即\(f[l,k]和f[r-2^k+1,k]\)两部分。答案就是这两部分取个\(max\)

代码

#include<bits/stdc++.h>
using namespace std;
int st[200010][20]={0},a[100010];
int n,m,l,r;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		st[i][0]=a[i];//初始化边界条件
	}
	for(int i=n;i>=1;i--)
	{
		for(int j=1;j<20;j++)
		{
			if((i+(1<<(j-1)))>n)continue;//如果越界就跳过
			st[i][j]=st[i][j-1]>st[i+(1<<(j-1))][j-1]?st[i][j-1]:st[i+(1<<(j-1))][j-1];//状态转移
		}
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&l,&r);
		int k=log2(r-l+1),ans;
		ans=(st[l][k]>st[r-(1<<k)+1][k])?st[l][k]:st[r-(1<<k)+1][k];//求出答案
		printf("%d\n",ans);
	}
    return 0;
}
 posted on 2022-06-30 19:28  hu_led  阅读(99)  评论(1编辑  收藏  举报