題目鏈接:Codeforces - Closest Equals
顯然可以離線。
然後對每一個詢問,我們按照右端點排序,之後只考慮左端點就行了,所以我們對每一對滿足的,我們就修改左邊的哪個值即可。
然後就變成了區間min,線段樹即可。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5e5+10;
int n,m,a[N],res[N],mi[N<<2]; map<int,int> mp;
struct node{int l,r,id;}t[N];
#define mid (l+r>>1)
void build(int p,int l,int r){
if(l==r){mi[p]=1e9; return ;}
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
mi[p]=min(mi[p<<1],mi[p<<1|1]);
}
void change(int p,int l,int r,int x,int v){
if(l==r){mi[p]=min(mi[p],v); return ;}
if(x<=mid) change(p<<1,l,mid,x,v);
else change(p<<1|1,mid+1,r,x,v);
mi[p]=min(mi[p<<1],mi[p<<1|1]);
}
int ask(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return mi[p];
if(qr<=mid) return ask(p<<1,l,mid,ql,qr);
else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);
else return min(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d %d",&t[i].l,&t[i].r),t[i].id=i;
sort(t+1,t+1+m,[](node a,node b){
return a.r<b.r;
});
int pos=1; build(1,1,n);
for(int i=1;i<=m;i++){
while(pos<=t[i].r){
if(mp[a[pos]]) change(1,1,n,mp[a[pos]],pos-mp[a[pos]]);
mp[a[pos]]=pos; pos++;
}
res[t[i].id]=ask(1,1,n,t[i].l,t[i].r);
}
for(int i=1;i<=m;i++)
if(res[i]==1e9) puts("-1");
else printf("%d\n",res[i]);
return 0;
}