先双指针,再RMQ,再二分,具体看注释
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,M=20;
int n,m,f[N][M],a[N],v[N],la[N]; //a数组为输入数组,f为RMQ数组
//v[i]为以下标i的元素为结尾的最长完美序列长度,la[i]是该序列的起始下标
void init() //RMQ的初始化
{
for(int j=0;j<M;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
{
if(!j) f[i][j]=v[i];
else f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
int get(int l,int r) //RMQ的查询,返回[l,r]之间的最大值
{
int len=r-l+1;
int k=log(len)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
unordered_map<int,int> mp;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
//以下是双指针做法,把v[i]和la[i]求出来
for(int i=1,j=1;i<=n;i++)
{
mp[a[i]]++;
while(j<=i&&mp[a[i]]>1) mp[a[j++]]--;
v[i]=i-j+1,la[i]=j;
}
init();
while(m--)
{
int a,b,res=INT_MIN;
scanf("%d%d",&a,&b);
a++,b++;
//二分,目的是把从左到右第一个起始位置没有超出a的完美序列找出来
int l=a,r=b;
while(l<r)
{
int mid=l+r>>1;
if(la[mid]>=a) r=mid;
else l=mid+1;
}
if(la[l]>=a)
{
printf("%d\n",max(l-a,get(l,b)));
}else printf("%d\n",b-a+1);
}
return 0;
}