poj 3368 RMQ 求最多出现次数的数
2013-04-10 10:57
393 查看
题意:
给定一个非降序序列,给出查询i,j,求出区间[i,j]中出现次数最多的数的出现次数
解法:
1.编码
把连续的数值编码为例如(1,3),数值1出现了3次
2.设计区段
把原始的a1...an分解进入各个区间,每个区间就是上面编码的一段
需要维护
①ai在哪个区间,num数组
②ai所在区间的左端点,leftt数组
③ai所在区间的右端点,rightt数组
④区间的数值
3.转换为RMQ问题(经典方法)
对于给定的区间以及区间里的个数,查询区间的最大值(就是RMQ)问题
4.求解
对于i, j分别求出所在区间
if 如果在同一区间 直接给出答案 j - i + 1
else
找出i到所在区间左端点求解距离rightt[i] - i + 1,找出j所在区间左端点的个数j - leftt[j] + 1,
求出两者最大值
再求出中间的区间的最大值
再求最大值就是结论
时间复杂度:
初始化构建为O(nlgn)复杂度,查询操作O(1)复杂度
给定一个非降序序列,给出查询i,j,求出区间[i,j]中出现次数最多的数的出现次数
解法:
1.编码
把连续的数值编码为例如(1,3),数值1出现了3次
2.设计区段
把原始的a1...an分解进入各个区间,每个区间就是上面编码的一段
需要维护
①ai在哪个区间,num数组
②ai所在区间的左端点,leftt数组
③ai所在区间的右端点,rightt数组
④区间的数值
3.转换为RMQ问题(经典方法)
对于给定的区间以及区间里的个数,查询区间的最大值(就是RMQ)问题
4.求解
对于i, j分别求出所在区间
if 如果在同一区间 直接给出答案 j - i + 1
else
找出i到所在区间左端点求解距离rightt[i] - i + 1,找出j所在区间左端点的个数j - leftt[j] + 1,
求出两者最大值
再求出中间的区间的最大值
再求最大值就是结论
时间复杂度:
初始化构建为O(nlgn)复杂度,查询操作O(1)复杂度
#include <iostream> #include <vector> #include <map> #include <list> #include <set> #include <deque> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <cctype> #include <cstdio> #include <iomanip> #include <cmath> #include <cstdio> #include <iostream> #include <string> #include <sstream> #include <cstring> #include <queue> using namespace std; ///宏定义 const int INF = 990000000; const int maxn = 110000 ; const int MAXN = maxn; ///全局变量 和 函数 const int maxlog = 20; int max(int a, int b) { return a > b ? a : b; } ////////////////////////////////////////////////////////////////////////// // 区间最*大*值 struct RMQ { int d[maxn][maxlog]; void init(const vector<int>& A) { int n = A.size(); for(int i = 0; i < n; i++) d[i][0] = A[i]; for(int j = 1; (1<<j) <= n; j++) for(int i = 0; i + (1<<j) - 1 < n; i++) d[i][j] = max(d[i][j-1], d[i + (1<<(j-1))][j-1]); } int query(int L, int R) { int k = 0; while((1<<(k+1)) <= R-L+1) k++; // 如果2^(k+1)<=R-L+1,那么k还可以加1 return max(d[L][k], d[R-(1<<k)+1][k]); } }; int n, q; int a[maxn], num[maxn], leftt[maxn], rightt[maxn]; RMQ rmq; int main() { ///变量定义 int i, j; while (1) { scanf("%d", &n); if (n == 0) break; scanf("%d", &q); for(int i = 0; i < n; i++) scanf("%d", &a[i]); a = a[n - 1] + 1; // 哨兵 int start = -1; vector<int> count; for(i = 0; i <= n; i++) { if(i == 0 || a[i] > a[i-1]) // 新段开始 { if(i > 0) { count.push_back(i - start); for(int j = start; j < i; j++) { num[j] = count.size() - 1; leftt[j] = start; rightt[j] = i - 1; } } start = i; } } rmq.init(count); while (q--) { int L, R, ans; scanf("%d %d", &L, &R); L--; R--; if (num[L] == num[R]) { ans = R - L + 1; } else { ans = max(R - leftt[R] + 1, rightt[L] - L + 1); if(num[L] + 1 < num[R]) ans = max(ans, rmq.query(num[L] + 1, num[R] - 1)); } printf("%d\n", ans); } } ///结束 return 0; }
相关文章推荐
- POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
- POJ 3368 Frequent values(RMQ 求区间出现最多次数的数字的次数)
- poj 3368 统计区间出现次数最多数个数 RMQ
- 【POJ 3368】【RMQ 或者 线段树】Frequent values【求出区间内连续出现次数最多的数的次数。】
- POJ 3368 Frequent values(RMQ 区间出现频率最多数字次数)
- (POJ3368)Frequent values <RMQ 求区间出现次数最多的数出现的次数>
- poj 2406 后缀数组dc3 板子 计算出现次数最多的循环节 dc3 板子
- POJ 3368—— Frequent values(频繁出现的数值UVA11235) RMQ
- poj 3693 求出现次数最多的连续重复子串(具体的串)黑盒
- [poj 3693]后缀数组+出现次数最多的重复子串
- poj 3368 RMQ(查询给定区间内频率最多的数字数量)
- UVA 11235 Frequent values 非递减序列 l r范围内 出现最多的数字次数 RMQ
- POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数
- poj 1743 后缀数组+二分答案 求一个串的最长无重叠的重复出现次数最多的子串
- (POJ3368)Frequent values <RMQ 求区间出现次数最多的数出现的次数>
- 出现次数最多的整数 --- 蓝桥杯
- 求一个字符串中连续出现的次数最多的子串
- *数组-10. 求整数序列中出现次数最多的数
- 找出数组中出现次数最多的前k个元素[leetcode题]
- zoj 2104 出现次数最多的字符串 两种姿势