UVA11235 - Frequent values

2 篇文章 0 订阅

RMQ

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAXN 100010
#define INF (~0U >> 2)
using std::max;
int d[100010][20], a[100010], num[100010], left[100010], right[100010], count[100010], value[100010];
void RMQ_init(int n) {
	for (int i = 1; i <= n; ++ i) d[i][0] = count[i];
	for (int j = 1; (1 << j) <= n; ++ j) {
		for (int i = 1; i + j - 1 <= n; ++ i)
			d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
	}
}

int RMQ(int L, int R) {
	if (L > R) return 0;
	int k = 0;
	while ((1 << (k + 1)) <= R - L + 1) k ++;
	return max(d[L][k], d[R - (1 << k) + 1][k]);
}
int main() {
	int n, q;
	while (scanf("%d", &n) != EOF) {
		if (n == 0) break;
		scanf("%d", &q);
		for (int i = 1; i <= n; ++ i)
			scanf("%d", &a[i]);
		int p = 1, cnt = 1, temp = a[1];
		left[1] = 1; right[n] = n; num[1] = 1;
		for (int i = 2; i <= n; ++ i) {
			if (a[i] != temp) {
				count[p] = cnt;
				value[p] = temp;
				left[i] = i;
				p ++;
				cnt = 1;
				temp = a[i];
			}
			else {
				left[i] = left[i - 1];
				cnt ++;
			}
			num[i] = p;
		}
		count[p] = cnt; value[p] = temp;
		temp = a[n];
		for (int i = n - 1; i >= 1; -- i) {
			if (a[i] == temp) {
				right[i] = right[i + 1];
			}
			else {
				right[i] = i;
				temp = a[i];
			}
		}
		RMQ_init(p);
		//for (int i = 1; i <= n; ++ i) printf("%d ", num[i]); puts("");
		//for (int i = 1; i <= n; ++ i) printf("%d ", left[i]); puts("");
		//for (int i = 1; i <= n; ++ i) printf("%d ", right[i]); puts("");
		//for (int i = 1; i <= p; ++ i) printf("%d ", value[i]); puts("");
		//for (int i = 1; i <= p; ++ i) printf("%d ", count[i]); puts("");
		for (int i = 0; i < q; ++ i) {
			int l, r;
			scanf("%d%d", &l, &r);
			if (num[l] == num[r]) {
				printf("%d\n", r - l + 1);
			}
			else {
				int res = max(right[l] - l + 1, max(r - left[r] + 1, RMQ(num[l] +1, num[r] - 1)));
				printf("%d\n", res);
			}
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值