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;
}