zoukankan      html  css  js  c++  java
  • RMQ ST算法

    【算法概述】

    ST表:一种利用dp求解区间最值的倍增算法。

    定义:f[i][j]表示i到i+2^j-1这段区间的最大值。

    预处理:f[i][0]=a[i]。即i到i区间的最大值就是a[i]。

    状态转移:将f[i][j]平均分成两段,一段为f[i][j-1],另一段为f[i+2^(j-1)][j-1]。

    两段的长度均为2^j-1。f[i][j]的最大值即这两段的最大值中的最大值。

    得到f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])。

    【模板】

    //poj 3264
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    #define MAXN 50010
    #define Max(x,y) (x>y?x:y)
    #define Min(x,y) (x>y?y:x)
    
    int maxsum[MAXN][20],minsum[MAXN][20];//表示从第i个数起连续2^j个数中的最大值/最小值
    
    void RMQ(int num)
    {
        for(int j=1;j<20;j++)
            for(int i=1;i<=num;i++)
            {
                if(i+(1<<j)-1 <= num)
                {
                    maxsum[i][j]=Max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
                    minsum[i][j]=Min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
                }
            }
    }
    
    int main()
    {
        int i,j,num,t,query;
        while(scanf("%d%d",&num,&query) != EOF)
        {
            for(i=1;i<=num;i++)
            {
                scanf("%d",&maxsum[i][0]);
                minsum[i][0]=maxsum[i][0];
            }
            RMQ(num);
            int st,en,maxl,minl;
            while(query--)
            {
                scanf("%d%d",&st,&en);
                int k=(int)((log(en-st+1))/log(2.0));
                maxl=Max(maxsum[st][k],maxsum[en-(1<<k)+1][k]);
                minl=Min(minsum[st][k],minsum[en-(1<<k)+1][k]);
                printf("%d
    ",maxl-minl);
            }
        }
        return 0;
    }
  • 相关阅读:
    一道题DP
    BZOJ 3155: Preprefix sum
    BZOJ:3209: 花神的数论题
    TJU 4087. box
    BZOJ1192: [HNOI2006]鬼谷子的钱袋
    概率DP
    Codeforces Round #253 (Div. 2) D题
    二维树状数组
    Codeforces Round #250 (Div. 2)
    莫比乌斯函数
  • 原文地址:https://www.cnblogs.com/czsharecode/p/9705318.html
Copyright © 2011-2022 走看看