学习——st表

st表

用来解决区间最大值最小值问题, O(nlogn)预处理,O(1)查询

思想:倍增
二维数组f的含义
f[i][j],指的是在序列的第i项,向后2^j个元素所包含序列间的最大(小)值。

所以f[i][j]表示从i到i + 2^j - 1的区间
已 i = 1为例
图中f[1][2]f[1][2]即可由max(f[1][1],f[3][1])max(f[1][1],f[3][1])转移来
在这里插入图片描述

int f[MAXN][21]; // 第二维的大小根据数据范围决定,不小于log(MAXN)
for (int i = 1; i <= n; ++i)
    f[i][0] = read(); // 读入数据
for (int i = 1; i <= 20; ++i)
    for (int j = 1; j + (1 << i) - 1 <= n; ++j)
//需要进行-1,由于总长度是从j开始,长度为(1 << i),结尾的位置为j + (1 << i) - 1
        f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);

注意1<<i 相当于 2的i次方

在这里插入图片描述

计算log

int s = log2(r - l + 1);

l + 2^s - 1尽可能靠近r 得s = log(r - l + 1)
在线查询

for (int i = 0; i < m; ++i)
{
    int l = read(), r = read();
    int s = log2[r - l + 1];//直接使用cmath中的log2函数
    printf("%d\n", max(f[l][s], f[r - (1 << s) + 1][s]));
}//在线查询

注意
查询时f的区间划分问题,f[l][s]表示从l开始经过2^s个数字,终点为l + 2^s - 1, f[r-2^s+1][s]表示终点为r

在这里插入图片描述
来自洛谷大佬的解释

来源 感谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值