[Acwing] AcWing 1273. 天才的记忆 ST表

前言

传送门 :

介绍

S T ST ST表基于倍增的思想,可以做到 O n l o g n Onlogn Onlogn预处理, O ( 1 ) O(1) O(1)的查询,不支持修改

思路

对于这种很常见的 R M Q RMQ RMQ问题,我们一般会如下操作 :

状态表示:

f [ i ] [ j ] f[i][j] f[i][j] 表从以 i i i为端点,向右跳 2 j − 1 2^j-1 2j1的区间中的最大值

状态转移 :
f [ i ] [ j ] = a [ i ] ( j = = 0 ) f[i][j]=a[i] (j==0) f[i][j]=a[i](j==0)
f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i + ( 1 < < j − 1 ) ] [ j − 1 ] ) f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]) f[i][j]=max(f[i][j1],f[i+(1<<j1)][j1])

为什么这么转移呢 ? 请看下图

在这里插入图片描述
[来自oi wiki]

查询操作 :

对于每个询问的 [ L , R ] [L,R] [L,R],我们把它分成两部分, f [ l , l + 2 s − 1 ] 和 f [ r − 2 s + 1 , r ] f[l,l+2^s-1]和f[r-2^s+1,r] f[l,l+2s1]f[r2s+1,r]

其中 s = l o g 2 ( r − l + 1 ) s=log_2(r-l+1) s=log2(rl+1)

取两个区间的最大值即可

Mycode

const int N = 2e5+10 , M  = 30;
int a[N];
int n,m;
int f[N][M];

void init(){
	for(int j = 0; j < M ;j  ++) {
		for(int i=1;i+(1<<j)-1 <= n;i ++ ){
			if(!j)f[i][j] = a[i];
			else f[i][j] = max(f[i][j-1],f[i+(1<<j-1)][j-1]);
		}
	}
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	
	init();
	
	
	cin>>m;
	while(m -- ){
		int l,r;cin>>l>>r;
		int len = r -l + 1;
		int k = log(len)/log(2);
		cout<<max(f[l][k],f[r-(1<<k)+1][k])<<endl;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值