模板:
区间最大(小)值,预处理RMQ_init()时间复杂度 O(nlogn),查询 O(1).
void RMQ_init(int *A,int n)
{
for(int i=1;i<=n;i++) d[i][0]=A[i];
for(int j=1;(1<<j) <=n;j++) // j表示长度 (1<<j)
for(int i=1;i+(1<<j)-1<=n;i++) // 从位置i开始 长度为(2<<j)的区间 最大值
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int l,int r)
{
int k=0;
while((1<<(k+1)) <=r-l+1) k++;
return max(d[l][k],d[r-(1<<k)+1][k]);
}
例题: UVA 11235
给出一个非降序排列的整数数组a[],长度n,你的任务是对于一系列询问(i,j),回答区间 [ai,aj]中出现次数最多的值出现的次数。
白书P198
#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define M 100000
using namespace std;
int a[M+5],value[M+5],cnt[M+5],L[M+5],R[M+5],num[M+5];
int d[M+5][20];
void RMQ_init(int *A,int n)
{
for(int i=1;i<=n;i++) d[i][0]=A[i];
for(int j=1;(1<<j) <=n;j++) // j表示长度 (1<<j)
for(int i=1;i+(1<<j)-1<=n;i++) // 从位置i开始 长度为(2<<j)的区间 最大值
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
int RMQ(int l,int r)
{
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,m;
while(~scanf("%d",&n) && n)
{
scanf("%d",&q);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
m=0;
int now=a[1],now_n=1,l=1;
num[1]=1;
for(int i=2;i<=n;i++)
if(now==a[i]) now_n++,num[i]=num[i-1];
else{
value[++m]=now;
cnt[m]=now_n;
L[m]=l;
R[m]=i-1;
num[i]=m+1;
now=a[i];
now_n=1;
l=i;
}
value[++m]=now;
cnt[m]=now_n;
L[m]=l;
R[m]=n;
/*
for(int i=1;i<=m;i++)
printf("%d : %d %d %d %d\n",i,value[i],cnt[i],L[i],R[i]);
for(int i=1;i<=n;i++)
printf("%d ",num[i]);
puts(""); */
RMQ_init(cnt,n);
int i,j;
int ans;
while(q--)
{
int p1,p2;
scanf("%d%d",&i,&j);
if(i>j) {int tmp=i;i=j;j=tmp;}
p1=num[i]; p2=num[j];
// printf("p1=%d p2=%d\n",p1,p2);
if(p1==p2) ans=j-i+1;
else if(p1+1==p2) ans=max(R[p1]-i+1,j-L[p2]+1);
else{
ans=max(R[p1]-i+1,j-L[p2]+1);
// printf("!%d\n",ans);
int x=RMQ(p1+1,p2-1);
ans=max(ans,x);
// printf("rmq=%d\n",RMQ(p1+1,p2-1));
}
printf("%d\n",ans);
}
}
return 0;
}