1. 程式人生 > >poj 3368 - RMQ

poj 3368 - RMQ

題目連結:https://vjudge.net/problem/POJ-3368

 

解題思路:

題目給出不降序列,

令f[i] = v[i]==v[i-1]? f[i]+1 : 1;

查詢區間f[i]的最大值可以RMQ,都是要對l進行剪下,使得v[l]的值是第一次出現的位置才行.

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n,m,a[mx],Max[mx][20];
int up[mx];
void RMQ(int N)
{
	for(int j=1;(1<<j)<=N;j++){
		int tmp = 1<<(j-1); 
		for(int i=1;i+tmp<=N;i++)
		Max[i][j] = max(Max[i][j-1],Max[i+tmp][j-1]);
	}
} 
int find(int x,int k)
{
	if(k<=0) return 0;
	int len = log(k)/log(2.0);
	return max(Max[x][len],Max[x+k-(1<<len)][len]);
}
int main()
{
	a[0] = 1e9;
	while(scanf("%d",&n)&&n)
	{
		a[n+1] = 1e9;
		scanf("%d",&m);
		for(int i=1;i<=n;i++){
			scanf("%d",a+i);
			if(a[i]==a[i-1]) Max[i][0] = Max[i-1][0] + 1;
			else Max[i][0] = 1;
		}
		for(int i=n;i>=1;i--){
			if(a[i]==a[i+1]) up[i] = up[i+1];
			else up[i] = i;
		}
		RMQ(n);
		int l,r;
		while(m--){
			scanf("%d%d",&l,&r);
			int ans = min(up[l],r)-l+1;
			ans = max(ans,find(up[l]+1,r-up[l]));
			printf("%d\n",ans);
		}
	}
	return 0;
}