zoukankan      html  css  js  c++  java
  • 九度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/

  • 相关阅读:
    HTML5之Canvas影片广场
    iOS英语—》中国本土化,如调用专辑,摄像头的变化“cancel”,“photos”至“撤消”,“摄像头”
    约瑟夫问题解决
    2014在百度之星资格赛的第二个问题Disk Schedule
    2015第30周二
    2015第30周一
    2015第29周日
    2015第29周六Spring
    2015第29周五AOP
    2015第29周四
  • 原文地址:https://www.cnblogs.com/liushaobo/p/4373815.html
Copyright © 2011-2022 走看看