题目地址: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. Visual Stadio 2015创建WebApplication应用和运行赏析

    专题图: 1,创建一个WebApplication应用 2,项目结构和布局  3,运行项目 作者:ylbtech出处:http://ylbtech.cnblogs.com/本文版权归作者和博客园共有, ...

  2. ylbtech-dbs:ylbtech-6,record(生活记录)

    ylbtech-dbs:ylbtech-6,record(生活记录) -- =============================================-- DatabaseName:R ...

  3. netty入门实例

    TimeServer.java package netty.timeserver.server; import io.netty.bootstrap.ServerBootstrap; import i ...

  4. IronPython调用C# DLL函数方法

    C# DLL源码 using System; using System.Collections.Generic; using System.Text; using System.Security.Cr ...

  5. C# Bitmap Save Generic GDI+ Error

    Image.Save 方法 (String) 将该 Image 保存到指定的文件或流. 命名空间:  System.Drawing程序集:  System.Drawing(在 System.Drawi ...

  6. C++学习4

    在C++中,定义函数时可以给参数指定一个默认的初始值.调用函数时,可以省略有默认值的参数.也就是说,如果用户指定了参数的值,那么就使用用户指定的值,否则使用参数的默认值. C++规定,默认参数只能放在 ...

  7. java获取对应字节数的内容

    每个英文字符占一字节 每个汉字当编码不同时字节数不同,utf-8中一个汉语字符占位3字节 示例: 获取任意一个字符串的前四个字节. Scanner sc = new Scanner(System.in ...

  8. 菜鸟-手把手教你把Acegi应用到实际项目中(6)

    在企业应用中,用户的用户名.密码和角色等信息一般存放在RDBMS(关系数据库)中.前面几节我们采用的是InMemoryDaoImpl,即基于内存的存放方式.这节我们将采用RDBMS存储用户信息. Us ...

  9. Ubuntu 12.04 gedit编辑器 中文乱码

    百度一下查看了很多关于这个问题的解决方法,无非是用通过配置编辑器修改键值来解决.但是由于我的ubuntu是12.04版本的,搜索到的很多方法都不能用,网上一般的解决办法如下: 打开“注册表”(从字面理 ...

  10. ubuntu设置vim语法高亮显示和自动缩进

    转自:http://nichael1983.blog.163.com/blog/static/114969433201002711850604/ 今天自己学习使用vim,当我在vim中输入程序时,默认 ...