九度OJ 1544 数字序列区间最小值

题目地址:http://ac.jobdu.com/problem.php?pid=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

An <O(N), O(sqrt(N))> solution

#include <stdio.h>
#include <math.h>
#include <limits.h>
 
void Preprocess (int arr[], int n, int loc[]){
    int i, j, k;
    int step;
    int min;
 
    step = (int)sqrt((double)n);
    i = j = k = 0;
    while (1){
        min = k*step;
        for (j=k*step+1; j<n && j<(k+1)*step; ++j){
            if (arr[min] > arr[j])
                min = j;
        }
        loc[k] = min;
        ++k;
        if (j >= n)
            break;
    }
}
 
int main(void){
    int n;
    int arr[100001];
    int loc[1000];
    int t;
    int i;
    int left;
    int right;
    int min;
    int step;
    int index;
 
    while (scanf ("%d", &n) != EOF){
        step = (int)sqrt((double)n);
        for (i=0; i<n; ++i){
            scanf ("%d", &arr[i]);
        }
        Preprocess (arr, n, loc);
        scanf ("%d", &t);
        while (t-- != 0){
            scanf ("%d%d", &left, &right);
            --left;
            --right;
            min = INT_MAX;
            while (left <= right && left % step != 0){
                if (arr[left] < min){
                    min = arr[left];
                }
                ++left;
            }
            while (left + step <= right){
                index = loc[left/step];
                if (arr[index] < min){
                    min = arr[index];
                }
                left += step;
            }
            while (left <= right){
                if (arr[left] < min){
                    min = arr[left];
                }
                ++left;
            }
            printf ("%d
", min);
        }
    }
 
    return 0;
}
/**************************************************************
    Problem: 1544
    User: 简简单单Plus
    Language: C
    Result: Accepted
    Time:330 ms
    Memory:1252 kb
****************************************************************/



Sparse Table (ST) algorithm

//Sparse Table (ST) algorithm
#include <stdio.h>
#include <math.h>
#include <limits.h>
  
#define MAX 100000
#define LOGMAX 20
  
void Preprocess (int M[MAX][LOGMAX], int arr[MAX], int n){
    int i, j;
  
    for (i = 0; i < n; ++i)
        M[i][0] = i;
    for (j = 1; 1 << j <= n; ++j){
        for (i = 0; i + (1 << j) - 1 < n; ++i){
            if (arr[M[i][j - 1]] < arr[M[i + (1 << (j - 1))][j - 1]])
                M[i][j] = M[i][j - 1];
            else
                M[i][j] = M[i + (1 << (j - 1))][j - 1];
        }
    }
}
  
int main(void){
    int n;
    int arr[MAX];
    int M[MAX][LOGMAX];
    int test;
    int left;
    int right;
    int i;
    int min;
    int k;
  
    while (scanf ("%d", &n) != EOF){
        for (i = 0; i < n; ++i){
            scanf ("%d", &arr[i]);
        }
        Preprocess (M, arr, n);
        scanf ("%d", &test);
        while (test-- != 0){
            scanf ("%d%d", &left, &right);
            --left;
            --right;
            k = 0;
            while ((1 << (k + 1)) < (right - left + 1))
                ++k;
            if (arr[M[left][k]] <= arr[M[right - (1 << k) + 1][k]])
                min = arr[M[left][k]];
            else
                min = arr[M[right - (1 << k) + 1][k]];
              
            printf ("%d
", min);
        }
    }
  
    return 0;
}
/**************************************************************
    Problem: 1544
    User: 简简单单Plus
    Language: C
    Result: Accepted
    Time:270 ms
    Memory:9040 kb
****************************************************************/

Segment trees

#include <stdio.h>
#include <math.h>
 
#define MAX 100000
#define MAXN 200000
 
void Initialize (int node, int b, int e, int M[MAXN], int arr[MAX], int n){
    if (b == e){
        M[node] = b;
    }
    else{
        //compute the values in the left and right subtrees
          Initialize(2 * node, b, (b + e) / 2, M, arr, n);
          Initialize(2 * node + 1, (b + e) / 2 + 1, e, M, arr, n);
        //search for the minimum value in the first and
        //second half of the interval
          if (arr[M[2 * node]] <= arr[M[2 * node + 1]])
              M[node] = M[2 * node];
          else
              M[node] = M[2 * node + 1];
    }
}
 
 int Query(int node, int b, int e, int M[MAXN], int arr[MAX], int i, int j)
  {
      int p1, p2;
    
  //if the current interval doesn't intersect
  //the query interval return -1
      if (i > e || j < b)
          return -1;
    
  //if the current interval is included in
  //the query interval return M[node]
      if (b >= i && e <= j)
          return M[node];
    
  //compute the minimum position in the
  //left and right part of the interval
      p1 = Query(2 * node, b, (b + e) / 2, M, arr, i, j);
      p2 = Query(2 * node + 1, (b + e) / 2 + 1, e, M, arr, i, j);
    
  //return the position where the overall
  //minimum is
      if (p1 == -1)
          //return M[node] = p2;
          return p2;
      if (p2 == -1)
          //return M[node] = p1;
           return p1;
      if (arr[p1] <=arr[p2])
          return p1;
      return p2;
  }
 
int main(void){
    int n;
    int arr[MAX];
    int M[MAXN];
    int t;
    int left;
    int right;
    int i;
    int index;
 
    while (scanf ("%d", &n) != EOF){
        for (i = 0; i < n; ++i){
            scanf ("%d", &arr[i]);
        }
        for (i=0; i<MAXN; ++i){
            M[i] = -1;
        }
        Initialize (1, 0, n - 1, M, arr, n);
        scanf ("%d", &t);
        while (t-- != 0){
            scanf ("%d%d", &left, &right);
            --left;
            --right;
            index = Query(1, 0, n - 1, M, arr, left, right); 
            printf ("%d
", arr[index]);
        }
    }
 
    return 0;
}
/**************************************************************
    Problem: 1544
    User: 简简单单Plus
    Language: C
    Result: Accepted
    Time:290 ms
    Memory:2016 kb
****************************************************************/



参考资料:http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor

                  http://dongxicheng.org/structure/lca-rmq/

                  http://dongxicheng.org/structure/segment-tree/

原文地址:https://www.cnblogs.com/liushaobo/p/4373815.html