POJ 3368 Frequent values 线段树 || RMQ
来源:互联网 发布:网络男神 编辑:程序博客网 时间:2024/06/05 02:24
题目:http://poj.org/problem?id=3368
题意:给定一个非递减数组,然后有一些查询,询问区间内出现次数最多的数的次数
思路:没想到用RMQ怎么做,用线段树的话,类似于之前做过的一题,要区间合并,好恶心。最后两种方法都写了
RMQ
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N = 100100;const int INF = 0x3f3f3f3f;int dp[20][N];int arr[N], num[N];void ST(int n){ for(int i = 1; i <= n; i++) dp[0][i] = num[i]; for(int i = 1; (1<<i) <= n; i++) for(int j = 1; j <= n - (1<<i) + 1; j++) dp[i][j] = max(dp[i-1][j], dp[i-1][j+(1<<(i-1))]);}int RMQ(int l, int r){ if(l > r) return 0; int k = (int)log2(r - l + 1); return max(dp[k][l], dp[k][r-(1<<k)+1]);}int main(){ int n, m, a, b; while(scanf("%d", &n), n) { scanf("%d", &m); memset(num, 0, sizeof num);//num数组统计到当前位置时某个数字出现的次数 arr[0] = INF; for(int i = 1; i <= n; i++) { scanf("%d", &arr[i]); if(arr[i] == arr[i-1]) num[i] = num[i-1] + 1; else num[i]++; } ST(n); while(m--) { scanf("%d%d", &a, &b); int k = a; while(k <= b && arr[a] == arr[k]) k++;//左起第一个数的次数不能RMQ查询,因为查询区间之外可能有这个数 printf("%d\n", max(k - a, RMQ(k, b))); } } return 0;}线段树
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int N = 100100;struct node{ int l, r, mx, lmx, rmx, lv, rv;//mx为区间中出现的最大次数,lmx为左端点出现次数,rmx为右端点出现次数,lv为左端点值,rv为右端点值}s[N*4];int arr[N];void push_up(int k){ s[k].lv = s[k<<1].lv, s[k].rv = s[k<<1|1].rv; s[k].lmx = s[k<<1].lmx; if(s[k<<1].lmx == (s[k<<1].r - s[k<<1].l + 1) && s[k<<1].rv == s[k<<1|1].lv) s[k].lmx += s[k<<1|1].lmx; s[k].rmx = s[k<<1|1].rmx; if(s[k<<1|1].rmx == (s[k<<1|1].r - s[k<<1|1].l + 1) && s[k<<1|1].lv == s[k<<1].rv) s[k].rmx += s[k<<1].rmx; if(s[k<<1].rv == s[k<<1|1].lv) s[k].mx = max(s[k<<1].mx, max(s[k<<1|1].mx, s[k<<1].rmx + s[k<<1|1].lmx)); else s[k].mx = max(s[k<<1].mx, s[k<<1|1].mx);}void build(int l, int r, int k){ s[k].l = l, s[k].r = r; if(l == r) { s[k].lv = s[k].rv = arr[l]; s[k].mx = s[k].lmx = s[k].rmx = 1; return; } int mid = (l + r) >> 1; build(l, mid, k << 1); build(mid + 1, r, k << 1|1); push_up(k);}int query(int l, int r, int k){ if(l <= s[k].l && s[k].r <= r) return s[k].mx; int mid = (s[k].l + s[k].r) >> 1; int res1 = -1, res2 = -1, res3 = -1; if(l <= mid) res1 = query(l, r, k << 1); if(r > mid) res2 = query(l, r, k << 1|1); if(s[k<<1].rv == s[k<<1|1].lv && l <= mid && r > mid) res3 = min(s[k<<1].r - l + 1, s[k<<1].rmx) + min(r - s[k<<1|1].l + 1, s[k<<1|1].lmx); return max(res1, max(res2, res3));}int main(){ int n, m, a, b; while(scanf("%d", &n), n) { scanf("%d", &m); for(int i = 1; i <= n; i++) scanf("%d", &arr[i]); build(1, n, 1); while(m--) { scanf("%d%d", &a, &b); printf("%d\n", query(a, b, 1)); } } return 0;}
0 0
- POJ 3368 Frequent values RMQ / 线段树
- POJ 3368 Frequent values 线段树 || RMQ
- 【POJ】3368-Frequent values(RMQ或线段树)
- POJ 3368 Frequent values(线段树/RMQ)
- poj 3368 Frequent values (RMQ或线段树)
- POJ 3368 Frequent values(RMQ/线段树区间合并)
- poj 3368 Frequent values //RMQ
- POJ 3368 Frequent Values(RMQ)
- [POJ 3368]Frequent values(RMQ)
- Frequent values - POJ 3368 RMQ
- POJ--3368--Frequent values【RMQ】
- POJ 3368 Frequent values (RMQ)
- POJ 3368 Frequent values(RMQ)
- POJ 3368 Frequent values (RMQ)
- POJ 3368 Frequent Values(RMQ)
- POJ 3368 Frequent values RMQ
- POJ 3368 Frequent values (RMQ)
- POJ 3368 Frequent values RMQ
- android:拍照,相册剪裁的实现方式
- 简单的一些我今天的收获,必须来点归纳
- opencv-角点检测
- Java基础--Java内存管理与垃圾回收
- L1-026. I Love GPLT-PAT团体程序设计天梯赛GPLT
- POJ 3368 Frequent values 线段树 || RMQ
- 如何在程序中,实现比大小的功能
- Subsets
- 2016.07.07【初中部 NOIP提高组 】模拟赛C
- L1-025. 正整数A+B-PAT团体程序设计天梯赛GPLT
- listview的优化---viewHolder的封装
- java 多线程剖析
- Python 练习册,每天一个小程序(0000)
- 转载:深入解读Python解析XML的几种方式