做法:RMQ+二分

思路:

1.我们将相同的数作为一个区间存下来,将两个的坐标分别作为区间的左右端点。再把两个端点的差放在一个数组中,然后题目可以转化为数组区间找最小值。由此可以想到RMQst表
2.因为存的左右端点是有序的,在每次询问时,我们可以二分查找,找到可以得出答案的范围。

代码

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp(aa,bb) make_pair(aa,bb)
#define _for(i,b) for(int i=(0);i<(b);i++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,b,a) for(int i=(b);i>=(a);i--)
#define mst(abc,bca) memset(abc,bca,sizeof abc)
#define X first
#define Y second
#define lowbit(a) (a&(-a))
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef long double ld;
const int N=5e5+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
const double PI=acos(-1.0);

int n,m,cnt,f[N][20],logn[N]; 
unordered_map<int,int> mp;
int l[N],r[N];

void init(){
    logn[1]=0;
    logn[2]=1;
    for(int i=3;i<=n;i++) {
        logn[i]=logn[i>>1]+1;
    }
}

void solve(){
    cin>>n>>m;
    init();
    rep(i,1,n){
        int a;cin>>a;
        if(mp.count(a)){
            int t=mp[a];
            mp[a]=i;
            if(cnt&&l[cnt]>=t) continue;
            l[++cnt]=t,r[cnt]=i,f[cnt][0]=r[cnt]-l[cnt];
        }
        else mp[a]=i;
    }

    for(int j=1;j<=logn[cnt];j++){
        for(int i=1;i<=cnt-(1<<j)+1;i++){
            f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
    while(m--){
        int x,y,s;
        cin>>x>>y;
        x=lower_bound(l+1,l+cnt+1,x)-l;
        y=upper_bound(r+1,r+cnt+1,y)-r-1;
        if(x>y){
            cout<<"-1\n";
            continue;
        }
        s=logn[y-x+1];
        cout<<min(f[x][s],f[y-(1<<s)+1][s])<<"\n";
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
#ifdef DEBUG
    freopen("F:/laji/1.in", "r", stdin);
//    freopen("F:/laji/2.out", "w", stdout);
#endif
//     int t;cin>>t;while(t--)
    solve();
    return 0;
}