题目背景
这是一道模板题。
题目描述
给定一个序列,多次询问一段区间 [ l , r ] [l,r] [l,r],求区间中相同的数的最远间隔距离。
序列中两个元素的间隔距离指的是两个元素下标差的绝对值。
输入格式
第一行一个整数 n n n,表示序列长度。
第二行 n n n 个整数,描述这个序列。
第三行一个整数 m m m,表示询问个数。
之后 m m m 行,每行两个整数 l , r l,r l,r 表示询问区间。
输出格式
共 m m m 行,每行一个整数表示答案。如果区间内不存在两个数相同,则输出 0 0 0。
样例 #1
样例输入 #1
8
1 6 2 2 3 3 1 6
5
1 4
2 5
2 8
5 6
1 7
样例输出 #1
1
1
6
1
6
提示
记 a i a_i ai 表示序列元素。
对于 40 % 40\% 40% 的数据,满足 1 ≤ a i ≤ 400 1\leq a_i \leq 400 1≤ai≤400, 1 ≤ n , m ≤ 60000 1\leq n,m\leq 60000 1≤n,m≤60000。
对于 100 % 100\% 100% 的数据,满足 1 ≤ n , m ≤ 2 ⋅ 1 0 5 1\leq n,m\leq 2\cdot 10^5 1≤n,m≤2⋅105, 1 ≤ a i ≤ 2 ⋅ 1 0 9 1\leq a_i\leq 2\cdot 10^9 1≤ai≤2⋅109。
题目思路
板子题
将询问编号按升序排序
那么具体的情况我们可以分成两种:
1、如果这个询问的左右端点在同一个块,那么我们可以直接暴力扫。
2、不在同一个块的,根据之前的排序,保证了左端点为同一个块时右端点的单调递增,这时我们只需要让左端点可以一直往左扫即可。
Code
#include<bits/stdc++.h>
using namespace std;
int n,m,a[200000+10],b[200000+10],pos[200000+10],L[200000+10],R[200000+10],mp[200000+10],ma[200000+10],mi[200000+10],fans[200000+10],block=0,ans=0;
struct node
{
int l,r,id;
}q[200000+10];
int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
s=s*10+(ch-'0'),ch=getchar();
return s*w;
}
bool cmp(node a,node b)
{
if(pos[a.l]!=pos[b.l])
return pos[a.l]<pos[b.l];
else
return a.r<b.r;
}
int main()
{
n=read();
block=sqrt(n);
for(int i=1;i<=n;++i)
{
b[i]=a[i]=read();
pos[i]=(i-1)/block+1;
}
for(int i=1;i<=pos[n];++i)
L[i]=(i-1)/block+1,R[i]=i*block;
if(R[pos[n]]>n)
R[pos[n]]=n;
sort(b+1,b+n+1);
int siz=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;++i)
a[i]=lower_bound(b+1,b+siz+1,a[i])-b;
m=read();
for(int i=1;i<=m;++i)
{
int l=read(),r=read();
q[i]=(node){l,r,i};
}
sort(q+1,q+m+1,cmp);
int l=1,r=0,lastblock=0;
for(int i=1;i<=m;++i)
{
if(pos[q[i].l]==pos[q[i].r])
{
int maxn=0;
for(int j=q[i].r;j>=q[i].l;--j)
{
if(!mp[a[j]])
mp[a[j]]=j;
else
maxn=max(maxn,mp[a[j]]-j);
}
for(int j=q[i].r;j>=q[i].l;--j)
mp[a[j]]=0;
fans[q[i].id]=maxn;
continue;
}
if(pos[q[i].l]!=lastblock)
{
while(r>R[pos[q[i].l]])
{
ma[a[r]]=mi[a[r]]=0;
r--;
}
while(l<R[pos[q[i].l]]+1)
{
ma[a[l]]=mi[a[l]]=0;
l++;
}
r=l-1;
ans=0;
lastblock=pos[q[i].l];
}
while(r<q[i].r)
{
r++;
if(mi[a[r]]==0)
ma[a[r]]=mi[a[r]]=r;
else
ma[a[r]]=r,ans=max(ans,ma[a[r]]-mi[a[r]]);
}
int l2=l,maxn=ans;
while(l2>q[i].l)
{
l2--;
if(ma[a[l2]]==0)
ma[a[l2]]=l2;
else
maxn=max(maxn,ma[a[l2]]-l2);
}
while(l2<l)
{
if(ma[a[l2]]==l2)
ma[a[l2]]=0;
l2++;
}
fans[q[i].id]=maxn;
}
for(int i=1;i<=m;++i)
printf("%d\n",fans[i]);
return 0;
}