zoukankan      html  css  js  c++  java
  • ST表解决RMQ问题

    RMQ问题:

    RMQ(Range Minimum/Maximum Query),区间最值查询。对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。

    RMQ问题可以用线段树和ST表解决。

    线段树:查询复杂度O(log n) 可以修改数列中的值

    ST表: 查询复杂度 O(1) 无法修改数列中的值,是在线算法

    其实ST表就是个动态规划
    核心思想:倍增

    对于dp[i][j] ,其含义为以i为起点,长度为2^j这个区间的最大值

    转移方程就是把这个区间分成两个小区间的最大值。
    https://www.luogu.com.cn/problem/P3865
    https://www.cnblogs.com/zwfymqz/p/8581995.html

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 5;
    
    int n,m;
    int dp[maxn][21];
    
    int main() {
        scanf("%d%d",&n,&m);
        int num;
        for(int i=1;i<=n;i++)  //初始化,区间长度为1,最大值就是本身
        {
            scanf("%d",&num);
            dp[i][0]=num;
        }
        for(int j=1;(1<<j)<=n;j++) //2^j 要大于等于区间长度
            for(int i=1;i+(1<<j)-1<=n;i++) //处理i到i+(1<<j)-1这个区间
            {
                dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); //将当前区间[i,i+2^j]拆分成[i,i+2^(j-1)] [i+2^(j-1),i+2^(j-1)+2^(j-1)].
            }                                                   //其实就是再中间切割一下 后边区间可以简写成[i+2^(j-1),i+2^j]
        int k;
        int l,r;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            k=log2(r-l+1);
            printf("%d
    ",max(dp[l][k],dp[r-(1<<k)+1][k]));
        }
        return 0;
    }
    
  • 相关阅读:
    《将博客搬至CSDN》
    所谓找链表中点
    虚函数
    编辑距离
    数组移位
    DFA
    Single Number III
    XOR异或解惑
    First Bad Version
    while(!in.empty()) 和 while(in.size())
  • 原文地址:https://www.cnblogs.com/chilkings/p/11947599.html
Copyright © 2011-2022 走看看