st表详解
介绍
st表可以静态维护区间最大值,与单调队列相比,st表可以在不定长的区间求解,而单调队列只可以在定长中求解
例题1:
P3865 【模板】ST 表 & RMQ 问题
题目背景
这是一道 ST 表经典题——静态区间最大值
请注意最大数据时限只有 0.8s,数据强度不低,请务必保证你的每次查询复杂度为 O ( 1 ) O(1) O(1)。若使用更高时间复杂度算法不保证能通过。
如果您认为您的代码时间复杂度正确但是 TLE,可以尝试使用快速读入:
inline int read()
{int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}return x*f;
}
函数返回值为读入的第一个整数。
快速读入作用仅为加快读入,并非强制使用。
题目描述
给定一个长度为 N N N 的数列,和 $ M $ 次询问,求出每一次询问的区间内数字的最大值。
输入格式
第一行包含两个整数 N , M N,M N,M,分别表示数列的长度和询问的个数。
第二行包含 N N N 个整数(记为 a i a_i ai),依次表示数列的第 i i i 项。
接下来 M M M 行,每行包含两个整数 l i , r i l_i,r_i li,ri,表示查询的区间为 [ l i , r i ] [l_i,r_i] [li,ri]。
输出格式
输出包含 M M M 行,每行一个整数,依次表示每一次询问的结果。
输入输出样例 #1
输入 #1
8 8
9 3 1 7 5 6 0 8
1 6
1 5
2 7
2 6
1 8
4 8
3 7
1 8
输出 #1
9
9
7
7
9
8
7
9
说明/提示
对于 30 % 30\% 30% 的数据,满足 1 ≤ N , M ≤ 10 1\le N,M\le 10 1≤N,M≤10。
对于 70 % 70\% 70% 的数据,满足 1 ≤ N , M ≤ 10 5 1\le N,M\le {10}^5 1≤N,M≤105。
对于 100 % 100\% 100% 的数据,满足 1 ≤ N ≤ 10 5 1\le N\le {10}^5 1≤N≤105, 1 ≤ M ≤ 2 × 10 6 1\le M\le 2\times{10}^6 1≤M≤2×106, a i ∈ [ 0 , 10 9 ] a_i\in[0,{10}^9] ai∈[0,109], 1 ≤ l i ≤ r i ≤ N 1\le l_i\le r_i\le N 1≤li≤ri≤N。
思路:
举一个例子来解释


代码:
#include<bits/stdc++.h>
using namespace std;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n,q;cin>>n>>q;int len=log2(n);vector st(len+1,vector<int>(n+1));for(int i=1;i<=n;i++)cin>>st[0][i];for(int i=1;i<=len;i++){for(int j=1;j<=(n-(1ll<<i)+1);j++){st[i][j]=max(st[i-1][j],st[i-1][j+(1<<(i-1))]);}}while(q--){int l,r;cin>>l>>r;int i=log2(r-l+1);int ans=max(st[i][l],st[i][r-(1<<i)+1]);cout<<ans<<'\n';}
}
例题2:
P2880 [USACO07JAN] Balanced Lineup G
题目描述
每天,农夫 John 的 n ( 1 ≤ n ≤ 5 × 1 0 4 ) n\ (1\le n\le 5\times 10^4) n (1≤n≤5×104) 头牛总是按同一序列排队。
有一天,John 决定让一些牛们玩一场飞盘比赛。他准备找一群在队列中位置连续的牛来进行比赛。但是为了避免水平悬殊,牛的身高不应该相差太大。John 准备了 q ( 1 ≤ q ≤ 1.8 × 1 0 5 ) q\ (1\le q\le 1.8\times10^5) q (1≤q≤1.8×105) 个可能的牛的选择和所有牛的身高 h i ( 1 ≤ h i ≤ 1 0 6 , 1 ≤ i ≤ n ) h_i\ (1\le h_i\le 10^6,1\le i\le n) hi (1≤hi≤106,1≤i≤n)。他想知道每一组里面最高和最低的牛的身高差。
输入格式
第一行两个数 n , q n,q n,q。
接下来 n n n 行,每行一个数 h i h_i hi。
再接下来 q q q 行,每行两个整数 a a a 和 b b b,表示询问第 a a a 头牛到第 b b b 头牛里的最高和最低的牛的身高差。
输出格式
输出共 q q q 行,对于每一组询问,输出每一组中最高和最低的牛的身高差。
输入输出样例 #1
输入 #1
6 3
1
7
3
4
2
5
1 5
4 6
2 2
输出 #1
6
3
0
思路:
可以使用两个st表来维护,一个维护最大值一个维护最小值即可
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n,q;cin>>n>>q;int len=log2(n);vector st1(len+1,vector<int>(n+1));vector st2(len+1,vector<int>(n+1));for(int i=1;i<=n;i++){cin>>st1[0][i];st2[0][i]=st1[0][i];}for(int i=1;i<=len;i++){for(int j=1;j<=(n-(1ll<<(i-1))+1);j++){st1[i][j]=max(st1[i-1][j],st1[i-1][j+(1ll<<(i-1))]);st2[i][j]=min(st2[i-1][j],st2[i-1][j+(1ll<<(i-1))]);}}while(q--){int l,r;cin>>l>>r;int i=log2(r-l+1);int mx=max(st1[i][l],st1[i][r-(1ll<<i)+1]);int mn=min(st2[i][l],st2[i][r-(1ll<<i)+1]);cout<<mx-mn<<'\n';}
}
例题3:
P7333 [JRKSJ R1] JFCA
题目描述
给出一个环,上面有 n n n 个点,每个相邻的点对之间的距离为 1 1 1。
每个点有两个属性 a i a_i ai 和 b i b_i bi,对于点 i i i,定义 f i f_i fi 为它与满足 i ≠ j i\ne j i=j 且 a j ≥ b i a_j\ge b_i aj≥bi 的 j j j 与 i i i 在环上的最短距离。特殊地,如果没有满足条件的 j j
