首页 > 其他 > 详细

[模板ST表]

时间:2019-11-14 15:57:52      阅读:104      评论:0      收藏:0      [点我收藏+]

P3865

[模板ST表]

题目大意:求[L,R]静态区间最大值

做法:

1:定义:\(f[i][j]\)表示\([i,i+2^{j}?1]\)这段长度为\(2^{j}\)的区间中的最大值。

2:\(RMQ\)问题:给定一个长度为\(N\)的区间,\(M\)个询问,每次询问\([L_i,R_i]\)这段区间元素的最大值/最小值。\(RMQ\)的高级写法一般有两种,即为线段树和\(ST\)表。本文主要讲解一下\(ST\)表的写法。(以区间最大值为例)ST表:一种利用\(dp\)思想求解区间最值的倍增算法。

3:预处理:\(f[i][0] = a[i]\)。即\([i,i]\)区间的最大值\(a_i\)

4:状态转移:将\([i,j]\)分成两段,设\(k=log_2^{j-i+1}\),一段为\([i,i+2^{k}?1]\),另一段为\([j-2^k+1,j]\)。两段的长度均为\(2^{k}\)\([i,j]\)的最大值即这两段的最大值中的最大值。

#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5+6;
int n,m,a[maxn],f[maxn][21];

void RMQ(int n)
{
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n && i+(1<<j-1)<=n;i++)
            f[i][j] = max(f[i][j-1],f[i+(1<<(j-1))][j-1]); 
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        f[i][0] = a[i];
    }
    RMQ(n);
    for(int i=1;i<=m;i++)
    {
        int L,R;
        scanf("%d%d",&L,&R);
        int k = (int)(log((double)(R - L + 1)) / log(2.0));// 保证 可以覆盖到i - j全部 数值 2^( 
        printf("%d\n",max(f[L][k],f[R - (1 << k) + 1][k]));
    }
    return 0;
}

[模板ST表]

原文:https://www.cnblogs.com/-Wind-/p/11857581.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!