ST表是用来求RMQ问题(求区间最大或最小值问题)的实用数据结构,支持(O(nlog_n))建立,(O(1))查询,是比较高效的结构
其原理实质上是DP(我最讨厌的东西)
题面:屠龙宝刀...
这是一道ST表经典题——静态区间最大值
请注意最大数据时限只有0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O(1)
本题所需处理仔细琢磨琢磨就是DP,先完成范围小一些的任务,然后再进行状态转移
转移方程(就是完成左右两区间处理后合并):
(f_{i,j}=max(f_{i,j-1},f_{i+2^{j-1},j-1}))
具体思想就是以每个节点为起点,保存此节点及往后的(2^i)个元素的最值,询问时进行覆盖询问,就是去小于((r-l+1))的最大(x)满足(2^x<(r-l+1))
然后进行询问:
(ans=max(f_{i,x},f_{r-2^x+1,x}))
当然,要预处理(log_2^{1-n}),用法见下面代码
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m;
int log[100005],maxn[100005][35],num[100005];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
log[0]=-1;
for(int i=1;i<=n;i++){
maxn[i][0]=num[i];
log[i]=log[i>>1]+1;
}
for(int j=1;j<=log[n];j++)
for(int i=1;i+(1<<j)-1<=n;i++)
maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
int s=log[b-a+1];
printf("%d
",max(maxn[a][s],maxn[b-(1<<s)+1][s]));
}return 0;
}