题意:给出n(n<=1e5)个从小到大排列的数,q(q<=1e5)次询问,输出[l,r]之内出现次数最多的数的次数。
思路:曾经好像做过,很熟悉。先离散化处理,将同一样的数合并,然后维护一个映射,映射每一个位置在第几个离散化后的快。在处理每一个离散化后的块的尾端坐标,然后结合[l,r]讨论就可以了。
const int maxn=100005;
int n,q;
int a[maxn*4];
int num[maxn];
int mp[maxn];
int c[maxn];
void build(int i,int l,int r)
{
if(l==r)
{
a[i]=num[l];
return ;
}
int mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
a[i]=max(a[i*2],a[i*2+1]);
}
int query(int L,int R,int i,int l,int r)
{
if(L<=l&&r<=R)
{
return a[i];
}
int ans=0;
int mid=(l+r)/2;
if(mid>=L) ans=max(ans,query(L,R,i*2,l,mid));
if(mid<R) ans=max(ans,query(L,R,i*2+1,mid+1,r));
return ans;
}
int main()
{
int t,cnt;
while(scanf("%d",&n)!=EOF)
{
if(n==0) break;
scanf("%d",&q);
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));//离散块的尾端坐标
memset(mp,0,sizeof(mp));//映射位置到离散块
scanf("%d",&t);
cnt=1;
num[1]=1;
mp[cnt]=1;
for(int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
if(x==t)
{
num[cnt]++;
mp[i]=cnt;
}
else
{
num[++cnt]=1;
t=x;
mp[i]=cnt;
c[cnt-1]=i-1;
}
}
c[cnt]=n;
build(1,1,n);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
if(mp[l]==mp[r])
{
cout<<r-l+1<<endl;
}
else if(mp[l]+1==mp[r])
{
int ans;
ans=c[mp[l]]-l+1;
ans=max(ans,r-c[mp[l]]);
cout<<ans<<endl;
}
else
{
int ans;
ans=c[mp[l]]-l+1;
ans=max(ans,r-c[mp[r]-1]);
ans=max(ans,query(mp[l]+1,mp[r]-1,1,1,n));
cout<<ans<<endl;
}
}
}
}