九度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/
九度OJ 1544 数字序列区间最小值的更多相关文章
- [Jobdu] 题目1544:数字序列区间最小值
题目描述: 给定一个数字序列,查询任意给定区间内数字的最小值. 输入: 输入包含多组测试用例,每组测试用例的开头为一个整数n(1<=n<=100000),代表数字序列的长度.接下去一行给出 ...
- 九度OJ 1349 数字在排序数组中出现的次数 -- 二分查找
题目地址:http://ac.jobdu.com/problem.php?pid=1349 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数 ...
- 九度OJ 1077 最大序列和 -- 动态规划
题目地址:http://ac.jobdu.com/problem.php?pid=1077 题目描述: 给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T的“序列和”. 对 ...
- 九度OJ 1251:序列分割 (DFS)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:166 解决:34 题目描述: 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值 比如{3,2,4,3,6} 可以分成{ ...
- 九度oj 1349 数字在排序数组中出现的次数
原题链接:http://ac.jobdu.com/problem.php?pid=1349 二分.. #include<algorithm> #include<iostream> ...
- 九度OJ,题目1089:数字反转
题目描述: 12翻一下是21,34翻一下是43,12+34是46,46翻一下是64,现在又任意两个正整数,问他们两个数反转的和是否等于两个数的和的反转. 输入: 第一行一个正整数表示测试数据的个数n. ...
- 九度oj题目1009:二叉搜索树
题目描述: 判断两序列是否为同一二叉搜索树序列 输入: 开始一个数n,(1<=n<=20) 表示有n个需要判断,n= 0 的时候输入结束. 接 ...
- 【九度OJ】题目1074:对称平方数 解题报告
[九度OJ]题目1074:对称平方数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1074 题目描述: 打印所有不超过n( ...
- 【九度OJ】题目1431:Sort 解题报告
[九度OJ]题目1431:Sort 解题报告 标签(空格分隔): 九度OJ [LeetCode] http://ac.jobdu.com/problem.php?pid=1431 题目描述: 给你n个 ...
随机推荐
- Struts2 Annotation 注解配置
也叫Zero Configuration(零配置),它省去了写xml文件的麻烦,可以直接在类叫进行配置,不用在java文件和xml文件中来回切换. 必须导入struts2-convention-plu ...
- repo安装
repo是使用python开发的一个用于多版本管理的工具,可以和git协作,简化git的多版本管理. repo安装: 1.新建~/bin,并将此目录包含在path变量中(如果已存在,且已在path变量 ...
- [Java] 02 String的常用方法
public class TestString{ public static void main(String[] args){ String str1 = "123"; Stri ...
- sikuli实例
代码: package selenium.sikuli; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; im ...
- Android - 禁止Gridview滚动
设置gridview 的touch事件,是ACTION_MOVE 的话返回true mDragGrid.setOnTouchListener(new OnTouchListener() { @Over ...
- .NET连接池的配置 【转】
ADO.Net 在数据库操作过程中默认打开了连接池,不需要再进行手工配置.这个特性可以使数据库操作时效率提高,但也要有相应的代码配合,才能真正提高程序效率. 1.连接字符串 ADO.Net 中的连接池 ...
- 安装配置opensips
opensips提供了一个视频教程(这个页面有下载链接,90M),参考教程 wget http://opensips.org/pub/opensips/1.9.1/src/opensips-1.9.1 ...
- ubuntu14.04配置Hive1.2.1
1.添加环境变量:vi ~/.bashrc #HIVE VARIABLES START export HIVE_HOME=/usr/local/hive-1.2.1 export PATH=$PATH ...
- What is Split Brain in Oracle Clusterware and Real Application Cluster (文档 ID 1425586.1)
In this Document Purpose Scope Details 1. Clusterware layer 2. Real Application Cluster (d ...
- Android:Activity的跳转
// 实际开发中常用的方法 Intent intent = new Intent(); intent.setClass(MainActivity.this, LoginActivity.class); ...