ST表(跳跃表)
解决静态区间最大值问题, O ( N l o g N ) O(NlogN) O(NlogN)预处理后, O ( 1 ) O(1) O(1)给出数列 A A A中下标在 l ∼ r l \sim r l∼r之间的数的最大值是多少
F [ i , j ] 表示数列 A 下标中在 A [ i , i + 2 j − 1 ] 区间的最大长度, i ∼ i + 2 j − 1 共 2 j 个数字 递推边界 F [ i , 0 ] = A [ i ] , 根据公式 F [ i ] [ j ] = m a x ( F [ i ] [ j − 1 ] , f [ i + 2 j − 1 ) ] [ j − 1 ] ) 询问时找出小于区间长度下最大的 K 次幂,因为 F [ l ] [ k ] , F [ r − 2 k + 1 ] [ k ] 一定可以覆盖 [ l , r ] O ( 1 ) 询问即可 F[i,j]表示数列A下标中在A[i,i+2^j-1]区间的最大长度,i \sim i+2^j-1 共2^j个数字\\递推边界F[i,0]=A[i],根据公式F[i][j]=max(F[i][j-1],f[i+2^{j-1})][j-1])\\ 询问时找出小于区间长度下最大的K次幂,因为F[l][k],F[r-2^k+1][k]一定可以覆盖[l,r]\\ O(1)询问即可 F[i,j]表示数列A下标中在A[i,i+2j−1]区间的最大长度,i∼i+2j−1共2j个数字递推边界F[i,0]=A[i],根据公式F[i][j]=max(F[i][j−1],f[i+2j−1)][j−1])询问时找出小于区间长度下最大的K次幂,因为F[l][k],F[r−2k+1][k]一定可以覆盖[l,r]O(1)询问即可
P3865 【模板】ST 表
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
const int N=1e6;
int w[N],n,m,M,f[N][20];
struct _ST
{
/*
O(NlogN)预处理区间最值,O(1)查询,数组下标从1开始
M=log(n)/log(2)+1;
由于在class外部不允许访问私有成员,所以这将导致编译出错。
*/
void init(){
memset(f,-1,sizeof f);
for(int j=0;j<M;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
if(!j)f[i][j]=w[i];
else f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){
int k=log(r-l+1)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
}_ST;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
_ST.init();
for(int i=1;i<=m;i++){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",_ST.query(l,r));
}
return 0;
}
P2251 质量检测
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
const int N=1e6;
int w[N],n,m,M,f[N][20];
struct _ST
{
/*
O(NlogN)预处理区间最值,O(1)查询,数组下标从1开始
M=log(n)/log(2)+1;
由于在class外部不允许访问私有成员,所以这将导致编译出错。
*/
void init(){
memset(f,0x3f,sizeof f);
for(int j=0;j<M;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
if(!j)f[i][j]=w[i];
else f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){
int k=log(r-l+1)/log(2);
return min(f[l][k],f[r-(1<<k)+1][k]);
}
}_ST;
int main()
{
cin>>n>>m;
M=log(n)/log(2)+1;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
_ST.init();
for(int i=1;i+m-1<=n;i++){
int l=i,r=l+m-1;
printf("%d\n",_ST.query(l,r));
}
return 0;
}
P1816 忠诚
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
const int N=1e5+10;
int w[N],n,m,M,f[N][20];
struct _ST
{
/*
O(NlogN)预处理区间最值,O(1)查询,数组下标从1开始
M=log(n)/log(2)+1;
由于在class外部不允许访问私有成员,所以这将导致编译出错。
*/
void init(){
memset(f,0x3f,sizeof f);
for(int j=0;j<M;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
if(!j)f[i][j]=w[i];
else f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){
int k=log(r-l+1)/log(2);
return min(f[l][k],f[r-(1<<k)+1][k]);
}
}_ST;
int main()
{
cin>>n>>m;
M=log(n)/log(2)+1;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
_ST.init();
for(int i=1;i<=m;i++){
int l,r;
scanf("%d%d",&l,&r);
printf("%d ",_ST.query(l,r));
}
return 0;
}
P2880 [USACO07JAN]Balanced Lineup G
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <map>
#include <vector>
#define pb push_back
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo2(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
const int N=1e5+10;
int w[N],n,m,M,f_max[N][16],f_min[N][16];
struct _ST
{
/*
O(NlogN)预处理区间最值,O(1)查询,数组下标从1开始
M=log(n)/log(2)+1;
由于在class外部不允许访问私有成员,所以这将导致编译出错。
*/
void init(){
memset(f_min,0x3f,sizeof f_min);
memset(f_max,-1,sizeof f_max);
for(int j=0;j<M;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
if(!j)f_min[i][j]=w[i];
else f_min[i][j]=min(f_min[i][j-1],f_min[i+(1<<(j-1))][j-1]);
}
}
for(int j=0;j<M;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
if(!j)f_max[i][j]=w[i];
else f_max[i][j]=max(f_max[i][j-1],f_max[i+(1<<(j-1))][j-1]);
}
}
}
int query_min(int l,int r){
int k=log(r-l+1)/log(2);
return min(f_min[l][k],f_min[r-(1<<k)+1][k]);
}
int query_max(int l,int r){
int k=log(r-l+1)/log(2);
return max(f_max[l][k],f_max[r-(1<<k)+1][k]);
}
}_ST;
int main()
{
cin>>n>>m;
M=log(n)/log(2)+1;
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
_ST.init();
for(int i=1;i<=m;i++){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",_ST.query_max(l,r)-_ST.query_min(l,r));
}
return 0;
}