• [Jobdu] 题目1544:数字序列区间最小值


    题目描述:

    给定一个数字序列,查询任意给定区间内数字的最小值。 

    输入:

    输入包含多组测试用例,每组测试用例的开头为一个整数n(1<=n<=100000),代表数字序列的长度。
    接下去一行给出n个数字,代表数字序列。数字在int范围内。
    下一行为一个整数t(1<=t<=10000),代表查询的次数。
    最后t行,每行给出一个查询,由两个整数表示l、r(1<=l<=r<=n)。

    输出:

    对于每个查询,输出区间[l,r]内的最小值。

    样例输入:
    5
    3 2 1 4 3
    3
    1 3
    2 4
    4 5
    样例输出:
    1
    1
    3

    RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。

    主要方法及复杂度如下:
    1、朴素(即搜索),O(n)-O(qn) online。
    2、线段树,O(n)-O(qlogn) online。
    3、ST(实质是动态规划),O(nlogn)-O(q) online。
    ST算法(Sparse Table),以求最大值为例,设d[i,j]表示[i,i+2^j-1]这个区间内的最大值,那么在询问到[a,b]区间的最大值时答案就是max(d[a,k], d[b-2^k+1,k]),其中k是满足2^k<=b-a+1(即长度)的最大的k,即k=[ln(b-a+1)/ln(2)]。
    d的求法可以用动态规划,d[i, j]=max(d[i, j-1],d[i+2^(j-1), j-1])。
    4、RMQ标准算法:先规约成LCA(Lowest Common Ancestor),再规约成约束RMQ,O(n)-O(q) online。
    首先根据原数列,建立笛卡尔树,从而将问题在线性时间内规约为LCA问题。LCA问题可以在线性时间内规约为约束RMQ,也就是数列中任意两个相邻的数的差都是+1或-1的RMQ问题。约束RMQ有O(n)-O(1)的在线解法,故整个算法的时间复杂度为O(n)-O(1)。
     
    下面是方法3的实现:
     1 #include <climits>
     2 #include <cmath>
     3 #include <cstdio>
     4 #include <iostream>
     5 using namespace std;
     6  
     7 int n, t;
     8 int l, r;
     9 int dp[100001][32];
    10  
    11 void init() {
    12     for (int j = 1; (1<<j) <= n; ++j) {
    13         for (int i = 1; i + (1<<j) - 1 <= n; ++i) {
    14             dp[i][j] = min(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
    15         }
    16     }
    17 }
    18  
    19 void getRes() {
    20     int k = (int) (log((double)(r-l+1))/log(2.0));
    21     int res =  min(dp[l][k], dp[r-(1<<k)+1][k]);
    22     printf("%d
    ", res);
    23 }
    24  
    25 int main() {
    26     while (scanf("%d", &n) != EOF) {
    27         for (int i = 1; i <= n; ++i) {
    28             scanf("%d", &dp[i][0]);
    29         }
    30         init();
    31         scanf("%d", &t);
    32         for (int i= 0; i < t; ++i) {
    33             scanf("%d %d", &l, &r);
    34             getRes();
    35         }
    36     }
    37     return 0;
    38 }
    39 /**************************************************************
    40     Problem: 1544
    41     User: hupo250
    42     Language: C++
    43     Result: Accepted
    44     Time:320 ms
    45     Memory:14068 kb
    46 ****************************************************************/
  • 相关阅读:
    数据处理之PostgreSQL过程语言学习
    Thinkphp中的assign() 和 display()
    JS截取与分割字符串常用技巧总结
    三种JS截取字符串方法
    十大经典排序算法的JS版
    js时间与毫秒互相转换
    javascript--清除表单缓存
    JS join()和split()方法、reverse() 方法、sort()方法
    JS数组去重的几种常见方法
    CSS样式大全
  • 原文地址:https://www.cnblogs.com/easonliu/p/4140990.html
Copyright © 2020-2023  润新知