(DP ST表 线段树)51NOD 1174 区间中最大的数
Posted ekalos-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(DP ST表 线段树)51NOD 1174 区间中最大的数相关的知识,希望对你有一定的参考价值。
给出一个有N个数的序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,最大的数是多少。
例如: 1 7 6 3 1。i = 1, j = 3,对应的数为7 6 3,最大的数为7。(该问题也被称为RMQ问题)
Input
第1行:1个数N,表示序列的长度。(2 <= N <= 10000) 第2 - N + 1行:每行1个数,对应序列中的元素。(0 <= S[i] <= 10^9) 第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 10000) 第N + 3 - N + Q + 2行:每行2个数,对应查询的起始编号i和结束编号j。(0 <= i <= j <= N - 1)
Output
共Q行,对应每一个查询区间的最大值。
Input示例
5 1 7 6 3 1 3 0 1 1 3 3 4
Output示例
7 7 3
解:
法一:ST表,算法思路简单,但其实不好写。
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 5 #define CLR(x) memset(x, 0, sizeof(x)) 6 #define MAX(a,b) (a > b ? a : b) 7 8 int dp[10005][15]; 9 10 void ST(int l) 11 { 12 for (int i = 1; (1 << i - 1) < l; ++i) 13 for (int j = 0; j + (1 << i - 1) < l; ++j) 14 dp[j][i] = MAX(dp[j][i - 1], dp[j + (1 << (i - 1))][i - 1]); 15 } 16 17 int main() 18 { 19 int n; 20 while (scanf_s("%d", &n) != EOF) 21 { 22 int q; 23 for (int i = 0; i < n; ++i) scanf_s("%d", &dp[i][0]); 24 ST(n); 25 scanf_s("%d", &q); 26 while (q--) 27 { 28 int i, j, k = 0; 29 scanf_s("%d%d", &i, &j); 30 while (i + (1 << k) < j - (1 << k) + 1) ++k; 31 printf("%d ", MAX(dp[i][k], dp[j - (1 << k) + 1][k])); 32 } 33 } 34 }
法二:按自己想法写的,本来想试试线段树,但感觉更像是树状数组。
1 #include <stdio.h> 2 #include <math.h> 3 #include <malloc.h> 4 5 #define MAX(a,b) (a>b?a:b) 6 #define MIN(a,b) (a<b?a:b) 7 8 int *p, len; 9 10 void build_tree(int n) 11 { 12 len = 1; 13 while (len < n) len <<= 1;//len >= n 14 p = (int *)calloc((len << 1), 4);//0~2*len-1,其中len~2*len-1存放基础数据 15 for (int i = len; i < n + len; i++) scanf_s("%d", &p[i]); 16 for (int i = len - 1; i > 0; i--) 17 p[i] = MAX(p[i << 1], p[i << 1 | 1]); 18 return; 19 } 20 21 int Search() 22 { 23 int l, r, max = 0; 24 scanf_s("%d%d", &l, &r); 25 while (l <= r) 26 { 27 int i = r - l + 1, j, temp = 0;//i为区域内数据个数。 28 if (l) j = l & -l;//j为以l为左端点包含数据的个数。0时为0(实为无穷大),需修改。 29 else j = 10000; 30 while (1 << (temp + 1) < MIN(i, j)) ++temp;//temp=log2(min(i,j)) 31 max = MAX(max, p[l + len >> temp]); 32 l += (1 << temp); 33 } 34 return max; 35 } 36 37 int main() 38 { 39 int n; 40 while (scanf_s("%d", &n) != EOF) 41 { 42 int q; 43 build_tree(n); 44 scanf_s("%d", &q); 45 while (q--) 46 printf("%d ", Search()); 47 free(p); 48 } 49 return 0; 50 }
以上是关于(DP ST表 线段树)51NOD 1174 区间中最大的数的主要内容,如果未能解决你的问题,请参考以下文章
51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)
51NOD1174 区间最大数 && RMQ问题(ST算法)