刘汝佳书上看到的问题,没有看题解做了一下,直接AC了,不多说了,直接上代码总的来说RMQ查找左部最大,右部最大,和交叉部最大的三者中的最大值
#include <utility>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
map<int, pair<int,int>>mmp;
int v[100005][20],vv[100005];
int n,q;
void m_build(){
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++){
int t=0;
if(vv[i+(1<<(j-1))-1]==vv[i+(1<<(j-1))])
t=min(mmp[vv[i+(1<<(j-1))-1]].second,i-1+(1<<j))-max(mmp[vv[i+(1<<(j-1))-1]].first,i)+1;
v[i][j]=max(t,max(v[i][j-1],v[i+(1<<(j-1))][j-1]));
}
}
int m_find(int l,int r){
int k=0;
while((1<<(k+1))<=r-l+1)k++;
int t=0;
if(vv[r-(1<<k)+1]==vv[l+(1<<k)-1])
t=min(r,mmp[vv[r-(1<<k)+1]].second)-max(l,mmp[vv[r-(1<<k)+1]].first)+1;
return max(t,max(v[l][k],v[r-(1<<k)+1][k]));
}
int main() {
while (scanf("%d",&n)!=EOF) {
if(n==0)
break;
scanf("%d",&q);
for(int i=1;i<=n;i++)
v[i][0]=1;
int s=1;
scanf("%d",&vv[1]);
for(int i=2;i<=n;i++){
scanf("%d",&vv[i]);
if(vv[i]!=vv[i-1]){
pair<int, int>x;
x.first=i-s;
x.second=i-1;
mmp[vv[i-1]]=x;
s=1;
}
else
s++;
}
pair<int, int>x;
x.first=n-s+1;
x.second=n;
mmp[vv[n]]=x;
m_build();
while (q--) {
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",m_find(l,r));
}
}
return 0;
}