首页 > 代码库 > UVA 11235 - Frequent values(RMQ)
UVA 11235 - Frequent values(RMQ)
UVA 11235 - Frequent values
题目链接
题意:给定一个升序数列,每次询问一个区间[l, r],求出其中相同数字最大的个数
思路:RMQ,由于是升序,所以数字大小相同的必然连在一块,先预处理出一共有多少段,每段包含多少个数字,和原数组中每个位置对应哪一段,最左边位置和最右边位置,然后每次询问的时候,可以把询问[L, R]的时候可以分成三段:
1、L到r[L]为一段,个数为R[L] - L + 1
2、l[R]到R为一段,个数为R - l[R] + 1
3、中间所有为一段,这一段就可以用RMQ求解,以个数为值
最后三段中个数较大的就是答案了
注意判断所选[L,R]只有1段和2段的情况
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 100005; int n, q, a[N], l[N], r[N], num[N], cnt[N], v, rmq[N][20]; void init() { v = 0; int count, pre; scanf("%d", &q); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); if (!i || a[i] != a[i - 1]) { pre = i; if (i) cnt[v++] = count; count = 0; } count++; num[i] = v; l[i] = pre; } cnt[v++] = count; for (int i = n - 1; i >= 0; i--) { if (i == n - 1 || a[i] != a[i + 1]) { pre = i; } r[i] = pre; } } void Build_RMQ(int* a, int n) { for (int i = 0; i < n; i++) rmq[i][0] = a[i]; for (int j = 1; (1<<j) <= n; j++) { for (int i = 0; i + (1<<j) - 1 < n; i++) { rmq[i][j] = max(rmq[i][j - 1], rmq[i + (1<<(j - 1))][j - 1]); } } } int Query(int l, int r) { if (l > r) return 0; int k = 0; while ((1<<(k + 1)) <= r - l + 1) k++; return max(rmq[l][k], rmq[r - (1<<k) + 1][k]); } void solve() { Build_RMQ(cnt, v); int L, R; while (q--) { scanf("%d%d", &L, &R); L--; R--; if (num[L] == num[R]) printf("%d\n", R - L + 1); else printf("%d\n", max(Query(num[L] + 1, num[R] - 1), max(r[L] - L + 1, R - l[R] + 1))); } } int main() { while (~scanf("%d", &n) && n) { init(); solve(); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。