广场舞老奶奶都看得懂的ST表

首先放一道模板题

忠诚

这看上去特别简单,直接暴力就可以。

#include<bits/stdc++.h>
using namespace std;
int a[100001],m,n,t,k,ans=9999999;
int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&t,&k);
        for(int j=t;j<=k;j++)ans=min(ans,a[j]);
        printf("%d ",ans);
        ans=9999999;
    }
}

但是提交之后,你会惊奇的发现,90分!太高了怎么优化呢?

这个时候,ST表就出场了(square table)

首先一个二维数组,定义f[i][j]为a[i]到a[i+1<<j-1]的最小值,只要你学过一点倍增,你就会觉得下面很好理解,当然,没学过也没关系,我们可以利用动态规划的思想,写出动态转移方程式。

f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);就相当于把这个区间切成两个部分。

接下来,双重循环,就可以了。

这样子,我们就有了一个ST表,当然,怎么查询呢?

很简单,你把查询的区间分成两个部分,再直接在ST表里面调用。

int k=log2(r-l+1);
return min(f[l][k],f[r-(1<<k)+1][k]);

好了,思路写完了,你可以开始自己写代码了。

这道题写完了,你肯定也会写区间最大值了,这种查询区间最大值和最小值的问题就是大名鼎鼎的RMQ。

除了最大值和最小值之外,ST还是用于解决 可重复贡献问题 的数据结构。

你可能问,可重复贡献问题是啥,请看下面

可重复贡献问题 是指对于运算 opt,满足x opt x =x,则对应的区间询问就是一个可重复贡献问题。例如,最大值有 max(x,x)=x,gcd 有 gcd(x,x)=x,所以 RMQ 和区间 GCD就是一个可重复贡献问题。像区间和就不具有这个性质,如果求区间和的时候采用的预处理区间重叠了,则会导致重叠部分被计算两次,这是我们所不愿意看到的。另外,opt还必须满足结合律才能使用 ST 表求解。

人话是什么?调用ST表时,大多数时候都会重合,而可重复贡献问题指的就是重合对结果正确性不产生影响的问题。

例题:

忠诚

单调栈、单调队列、RMQ - 题单 - 洛谷 | 计算机科学教育新生态(题单)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值