RMQ问题 ST 算法总结 poj3264

sparse table algorithm 简称ST算法,可以用于求解RMQ问题(range minimum query)
ST算法是一个在线算法,在线算法即对于每一个查询可以马上给出解答。但需要较长的时间来进行预处理。
在O(nlogn)的时间内进行预处理,而可以在O(1)的时间内解答每个询问。
预处理:
ST算法预处理利用的是dp的思想。
定义状态dp[i][j] 表示的是从第i个数起2^j个数中最小的数。
举一个例子:
2 9 1 4 5 3 4 5 6这个序列
dp[0][0] 为2 dp[0][1] = 2 dp[0][2] = 1
初始化这个dp数组,dp[i][0] = a[i] (0<i<n)
状态的转移:
可以发现dp[i][j]代表的数字一定是一个偶数(j = 0 除外),考虑将2^j的长度分成两份,长度都为2^(j-1)。
两端分别为 i ~ i + 2^(j-1)-1 , i + 2^(j-1) ~ i + 2^j - 1
沿着这思路转移方程:
dp[i][j] = min(dp[i][j-1],dp[i + 2^(j-1)][j-1]) ( 0<= , 2^j < n ,1 <= i < n - 2^j + 1)
查询:
RMQ(i,j) 查询 i ~ j 之间
区间长度len = j - i + 1。求出 2^k <= len < 2^(k+1)
k = log(len) / log(2) ( log 在c语言中同时以e为底)
RMQ(i,j) = min(dp[i][k] , dp[j - 2^k + 1][k])
(这里第二个参数要用dp[j - 2^k + 1][k] 不能用dp[i + 2^k - 1][k] ,因为后者可能是没有定义的)
例如
1 7 3 4 2 5
查询RMQ(0,4) len = 5,k = 2;
dp[0][2] = 1, dp[j - 2^k + 1][2] = dp[1][2] = 2 ,而dp[i + 2^k - 1][k] = dp[0 + 4 - 1][2] 这是没有定义的,因为 3 + 2^2 -1 = 6 >= n,这个在状态转移的时候是不会被更新的,因为这个数组本身没有这么长,这一段在中间的时候就已经到达数组结尾了。

poj 3264

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define M 50009
int a[M];
int mm[M][100];
int mi[M][100];
int n,q;
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d %d",&n,&q) == 2)
    {
        for(int i = 0;i < n;i++) scanf("%d",&a[i]);
        for(int i = 0;i < n;i++)
        {
            mm[i][0] = a[i];
            mi[i][0] = a[i];
        }
        for(int j = 1;(1<<j) <= n;j++)
        {
            for(int i = 0;i + (1<<j) - 1 < n;i++)
            {
                int m = i + (1<<(j-1));
                mm[i][j] = max(mm[i][j-1],mm[m][j-1]); // i ~ i + 2^(j-1)-1 , i + 2^(j-1) ~ i + 2^j - 1
                mi[i][j] = min(mi[i][j-1],mi[m][j-1]);
            }
        }
        while(q--)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            a--;
            b--;
            int len = b - a + 1;
            int m = (int)(log((double)len) / log(2.0));
            int maxx = max(mm[a][m],mm[b-(1<<m)+1][m]);
            int minn = min(mi[a][m],mi[b-(1<<m)+1][m]);
            printf("%d\n",maxx - minn);
        }
    }
    return 0;
}
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值