题意:你被给予了一个非单调递减的n个数字的序列a1, a2, ..., an。除此之外,你被给予了q个询问,每个询问由i, j(1 <= i <= j <= n)。求这个区间内出现最多的数的次数。

分析:这是一个非单调递减的序列,比如样例中的-1 -1 1 1 1 1 3 10 10 10,我们可以得到每个连续相等区间的数字次数为2 4 1 3,这个序列可以用RMQ维护。但是询问中的[L, R]不一定是正好在某个连续区间的边界,因此,我们可以求出左右两个多出来的区间部分的数的次数,中间连续的区间再用RMQ查询。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;
const int N = 100005;
const int M = 18;
int f[N], val[N], pos[N];
int l[N], r[N];
int g[N], idx;
int dp[N][M];
int n, q;

void init()
{
	for(int j = 0; j < M; ++j)
		for (int i = 1; i + (1 << j) - 1 <= idx; ++i)
		{
			if (!j) dp[i][j] = g[i];
			else dp[i][j] = max(dp[i][j - 1], dp[i + (1 << j - 1)][j - 1]);
		}
}

int query(int L, int R)
{
	int p = pos[L], q = pos[R];
	if (p == q)
	{
		return R - L + 1;
	}
	else
	{
		int k1 = r[p] - L + 1;
		int k2 = R - l[q] + 1;
		++p, --q;
		if (p <= q)
		{
			int len = q - p + 1;
			int t = log((double)len) / log((double)2);
			return max(max(k1, k2), max(dp[p][t], dp[q - (1 << t) + 1][t]));
		}
		else
		{
			return max(k1, k2);
		}
	}
	
}

void clear()
{
	idx = 0;
	memset(dp, 0, sizeof dp);
}

int main()
{
	while (scanf("%d", &n) != EOF)
	{
		if (n == 0) break;
		scanf("%d", &q);
		for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);

		int i;
		for (i = 1; i <= n; ++i)
		{
			if (val[i] == val[i - 1] && i - 1 != 0)
			{
				f[i] = f[i - 1] + 1;
			}
			else
			{
				l[idx] = i - f[i - 1], r[idx] = i - 1;
				g[idx] = f[i - 1];
				f[i] = 1;
				++idx;
			}
			pos[i] = idx;
		}
		l[idx] = i - f[i - 1], r[idx] = i - 1;
		g[idx] = f[i - 1];

		init();

		int l, r;
		while (q--)
		{
			scanf("%d%d", &l, &r);
			printf("%d\n", query(l, r));
		}
		clear();
	}


	return 0;
}