题目地址: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. JavaScript 类

    一.基础 //定义obj类 var obj = function(){ //声明v1成员 var v1 = ''; //声明get_v1方法,用this关键字定义 this.get_v1 = func ...

  2. mac eclipse 下安装subclipse

    参考 http://www.cnblogs.com/yinxiangpei/articles/3859057.html 推荐安装homebrew 在安装javahl时注意版本对应 http://sub ...

  3. 使用POI读取excel文件内容

    1.前言 项目中要求读取excel文件内容,并将其转化为xml格式.常见读取excel文档一般使用POI和JExcelAPI这两个工具.这里我们介绍使用POI实现读取excel文档. 2.代码实例: ...

  4. EF中使用SQL语句或存储过程

    EF中使用SQL语句或存储过程 1.无参数查询var model = db.Database.SqlQuery<UserInfo>("select* from UserInfoe ...

  5. crm 2011 plugin setparent setbusiness 用户更改经理 更改办事处

    背景: 在更改经理或者更改办事处时,使用plugin处理相应的团队. 问题:plugin写完,注册时发现使用update注册没有效果,然后bing得到,这里要使用setbusiness 和 setpa ...

  6. 封装一个简单好用的打印Log的工具类And快速开发系列 10个常用工具类

    快速开发系列 10个常用工具类 http://blog.csdn.net/lmj623565791/article/details/38965311 ------------------------- ...

  7. pymongo带认证连接mongo

    import pymongo connection = pymongo.MongoClient("127.0.0.1") connection.database.authentic ...

  8. java流布局管理器

    public class FlowLayoutPosition extends JFrame{    public FlowLayoutPosition()    {        setTitle( ...

  9. Android——开发环境

    sdk manager——>Tools 开发的工具类 sdk manager——>Extras——>Android support Library 支持高版本应用向低版本兼容 sdk ...

  10. linux包转发开发

    28号晚上接到这个任务的, 看了点epoll, 29号上午安装Ubuntu 12.10的G++, 开始把内网的vm虚拟机文件, 复制到外网, 重新建立一个虚拟机再更新, 最后外网也没能安装得了g++. ...