题目地址: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/

九度OJ 1544 数字序列区间最小值的更多相关文章

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

    题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的开头为一个整数n(1<=n<=100000),代表数字序列的长度.接下去一行给出 ...

  2. 九度OJ 1349 数字在排序数组中出现的次数 -- 二分查找

    题目地址:http://ac.jobdu.com/problem.php?pid=1349 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数 ...

  3. 九度OJ 1077 最大序列和 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1077 题目描述: 给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T的“序列和”. 对 ...

  4. 九度OJ 1251:序列分割 (DFS)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:166 解决:34 题目描述: 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值   比如{3,2,4,3,6} 可以分成{ ...

  5. 九度oj 1349 数字在排序数组中出现的次数

    原题链接:http://ac.jobdu.com/problem.php?pid=1349 二分.. #include<algorithm> #include<iostream> ...

  6. 九度OJ,题目1089:数字反转

    题目描述: 12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,现在又任意两个正整数,问他们两个数反转的和是否等于两个数的和的反转. 输入: 第一行一个正整数表示测试数据的个数n. ...

  7. 九度oj题目1009:二叉搜索树

    题目描述: 判断两序列是否为同一二叉搜索树序列 输入:                        开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...

  8. 【九度OJ】题目1074:对称平方数 解题报告

    [九度OJ]题目1074:对称平方数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1074 题目描述: 打印所有不超过n( ...

  9. 【九度OJ】题目1431:Sort 解题报告

    [九度OJ]题目1431:Sort 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1431 题目描述: 给你n个 ...

随机推荐

  1. 在eclipse中下载包含子模块(Submodules)的git项目

    先将项目下载下来 , 这时由于是子项目的原因 , 下载的项目中不包含任何子项目 . 这时在eclipse的Git Repositories中 , 选中Submodules , 右键点击update即可 ...

  2. Cassandra在Windows上安装及使用方法

    http://archive.apache.org/dist/cassandra/2.1.2/ http://docs.datastax.com/en/landing_page/doc/landing ...

  3. 利用 Gitbook 生成文档中心站点

    经过一个多月,Bugtags 最近上线了自己的文档站点:docs.bugtags.com,在这里你可以找到 Bugtags 集成.使用相关的绝大部分问题. 在这之前我们使用的是第三方提供的帮助中心产品 ...

  4. .NET单元测试

    原文链接:http://www.cnblogs.com/edisonchou/p/5467573.html

  5. 创建一个struts2的HelloWorld

    1.下载struts2的jar包 http://struts.apache.org/download.cgi#struts255 下载一个稳定版本Struts 2.3.31 里面提供了maven ja ...

  6. Bitbucket使用方法

    一.软件及SSH keys: 由于我的Bitbucket账号的邮箱及用户名与Github相同,所以SSH Public Keys可以用Github的,登录Bitbucket,悬浮在用户名boliqua ...

  7. [ActionScript 3.0] AS3动画类Tweener中滤镜的运用

    package { import caurina.transitions.Tweener; import caurina.transitions.properties.FilterShortcuts; ...

  8. 理论沉淀:隐马尔可夫模型(Hidden Markov Model, HMM)

    理论沉淀:隐马尔可夫模型(Hidden Markov Model, HMM) 参考链接:http://www.zhihu.com/question/20962240 参考链接:http://blog. ...

  9. ArcGIS上根据经纬度求地球表面两点间距离的实现

    ArcGIS上根据经纬度求地球表面两点间距离的实现 以米为单位..Net2.0,C#实现.        public static double DistanceOfTwoPoints(double ...

  10. html标签属性

    clientWidth = width + paddingclientHeight = height + paddingoffsetWidth = width + padding + borderof ...