现在有一个序列 a1, a2, ..., an ,还有m个查询 lj, rj (1 ≤ lj ≤ rj ≤ n) 。对于每一个查询,请找出距离最近的两个元素 ax 和 ay (x ≠ y) ,并且满足以下条件:
· lj ≤ x, y ≤ rj;
· ax = ay。
两个数字的距离是他们下标之差的绝对值 |x − y| 。
Input
单组测试数据。 第一行有两个整数n, m (1≤n,m≤5*10^5),表示序列的长度和查询的次数。 第二行有n个整数a1,a2,...,an (-10^9≤ai≤10^9)。 接下来有m行,每一行给出两个整数lj,rj (1≤lj≤rj≤n)表示一个查询。
Output
对于每一个查询,输出最近的距离,如果没有相等的元素,输出-1。
Input示例
样例输入1 5 3 1 1 2 3 2 1 5 2 4 3 5
Output示例
样例输出1 1 -1 2
题解:
将查询按右端点从小到大排序,将a离散化下来存入线段树,每次读到a[i]把左边离它最近的a[j]的位置上插入i和j的距离,线段树中保存最小值,最后对于每个查询在线段树中查询答案即可。
代码(加读入输出优化,不然过不去):
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct aaa{
int aa,bb;
}b[1000000];
struct bbb{
int ll,rr,pos;
}ans[1000000];
int inf=10000000,n,m,n1,a[1000000],f[2000000],sum[1000000],c[1000000],d[1000000],la[1000000];
int read(){
int sum=0,p=1;
char c=getchar();
while (c<'0'||c>'9') {
if (c=='-') p=-p;
c=getchar(); }
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum*p;
}
inline void write(int x){
if (x<0) putchar('-'),x=-x;
if (x>=10) write(x/10);
putchar('0'+x%10);
}
bool cmp(aaa a,aaa b){
return a.aa<b.aa;
}
bool kmp(bbb a,bbb b){
return a.rr<b.rr;
}
void build(int x,int l,int r){
if(l==r){
f[x]=inf;
return;
}
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
f[x]=inf;
}
void insert(int x,int l,int r,int t,int k){
if(l==r){
f[x]=min(f[x],k);
return;
}
int mid=(l+r)/2;
if(mid>=t)insert(x*2,l,mid,t,k);
else insert(x*2+1,mid+1,r,t,k);
f[x]=min(f[x*2],f[x*2+1]);
}
int query(int x,int l,int r,int t,int k){
if(l==t&&r==k)return f[x];
int mid=(l+r)/2;
if(mid>=k)return query(x*2,l,mid,t,k);
else if(t>mid)return query(x*2+1,mid+1,r,t,k);
else return min(query(x*2,l,mid,t,mid),query(x*2+1,mid+1,r,mid+1,k));
}
int main(){
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
a[i]=read();
b[i].aa=a[i];
b[i].bb=i;
}
for(i=1;i<=m;i++){
ans[i].ll=read();ans[i].rr=read();
ans[i].pos=i;
}
sort(b+1,b+n+1,cmp);
sort(ans+1,ans+m+1,kmp);
for(i=1;i<=n;i++){
if(b[i].aa!=b[i-1].aa||i==1)n1++;
c[b[i].bb]=n1;
}
build(1,1,n);
memset(d,-1,sizeof(d));
for(i=1;i<=n;i++){
if(d[c[i]]!=-1){
la[i]=d[c[i]];
d[c[i]]=i;
}
else d[c[i]]=i;
}
for(i=1,j=1;i<=n,j<=m;i++){
if(la[i])insert(1,1,n,la[i],i-la[i]);
while(j<=m&&i==ans[j].rr){
sum[ans[j].pos]=query(1,1,n,ans[j].ll,ans[j].rr);
j++;
}
}
for(i=1;i<=m;i++)
write(sum[i]<inf?sum[i]:-1),putchar('\n');
}