码迷,mamicode.com
首页 > 其他好文 > 详细

模板 - 数据结构 - ST表

时间:2019-03-04 20:46:39      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:pac   模板   根据   amp   bit   查询   its   状态转移方程   nlogn   

区间最大值,nlogn预处理,1查询,不能动态修改。

 

令 $f[i][j]$ 表示 $[i,i+2^j-1]$ 的最大值。

显然, $f[i][0]=a[i]$ 。 

根据定义式,写出状态转移方程: $f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1])$ 。

我们可以这么理解:将区间 $[i,i+2^j-1]$ 分成相同的两部分

中点即为 $(i+(i+2^j-1))/2=i+2^{j-1}-1/2$ 

所以 $[i,i+2^j-1]$ 可以分成 $[i,i+2^{j-1}-1]$ 和 $[i+2^j,i+2^j-1]$ 

 

对于每个询问 $[x,y]$ ,我们把它分成两部分 $f[x][s],f[y-2^s+1][s]$ 

其中 $s=log_2(y-x+1)$ ,虽然这两个区间有重叠,但是重叠不会影响区间的最大值

#include <bits/stdc++.h>
using namespace std;
const int logn = 21;
const int maxn = 2000001;
long long a[maxn], f[maxn][logn], Logn[maxn];
inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    while (c < 0 || c > 9) {
        if (c == -)
            f = -1;
        c = getchar();
    }
    while (c >= 0 && c <= 9) {
        x = x * 10 + c - 0;
        c = getchar();
    }
    return x * f;
}
void pre() {
    Logn[1] = 0;
    Logn[2] = 1;
    for (int i = 3; i <= maxn; i++) {
        Logn[i] = Logn[i / 2] + 1;
    }
}
int main() {
    int n = read(), m = read();
    for (int i = 1; i <= m; i++)
        f[i][0] = read();
    pre();
    for (int j = 1; j <= logn; j++)
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
            f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
    for (int i = 1; i <= m; i++) {
        int x = read(), y = read();
        int s = Logn[y - x + 1];
        printf("%d\n", max(f[x][s], f[y - (1 << s) + 1][s]));
    }
    return 0;
}

 

模板 - 数据结构 - ST表

标签:pac   模板   根据   amp   bit   查询   its   状态转移方程   nlogn   

原文地址:https://www.cnblogs.com/Yinku/p/10472788.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!