【HDU 1806】RMQ秒之

1.题目链接。题目大意,给定一个不递减的序列,询问时区间询问,[l.r]种出现最多的数出现了多少次?

2.开始题读错了,以为是让我输出这个数是多少???然后看了一下样例,发现题读错了,行吧,正解可以用权值线段树,最简单那就是RMQ了。做一个C数组,C[i]代表a[i]已经在前边出现了多少次,对于每一个询问,然后首先分割区间,因为我们需要找到一个起点做RMQ,也就是我们找到,一个C[i]=1的地方,左边最大值就是cur-l,右边就是RMQ(cur,r).二者取个最大值即可。

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 1e5 + 5;
int n, q, x, y, a[maxn], c[maxn], dp[maxn][20];
void ST()
{
	for (int i = 1; i <= n; i++) dp[i][0] = c[i];
	for (int j = 1; (1 << j) <= n; j++)
		for (int i = 1; i + (1 << j) - 1 <= n; i++)
			dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
int RMQ(int l, int r)
{
	if (l > r) return 0;
	int k = (int)(log(r - l + 1.0) / log(2.0));
	return max(dp[l][k], dp[r - (1 << k) + 1][k]);
}
int main()
{
	while (~scanf("%d", &n) && n)
	{
		scanf("%d", &q);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		c[1] = 1;
		for (int i = 2; i <= n; i++)
		{
			if (a[i] == a[i - 1]) c[i] = c[i - 1] + 1;
			else c[i] = 1;
		}

		ST();
		while (q--)
		{
			scanf("%d%d", &x, &y);
			int k = x;
			while (c[k] != 1 && k <= y) k++;
			int ans = max(k - x, RMQ(k, y));
			printf("%d\n", ans);
		}
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/89609817
今日推荐