九度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\n", 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\n", 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\n", 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/

 

你可能感兴趣的:(序列)