分析

当我们看到区间的多次查询时,首先想到的可能就是离线了
我们尝试将查询的区间右端点排序
那么我们在向右移动指针时
如果前边出现了这个值
那么就可以将Pre[i]更改为i-Pre[i]
因为我们现在还没有扩展到右边的点
所以我们可以直接区间查询的最小值
线段树即可
因为我们需要将数值作为下标,所以需要离散化一次


当然,此题还有ST表+二分做的,可以参考这位巨佬或者这位巨佬


蒟蒻有一个神奇的思想--三维偏序,但感觉空间开不下。。。故咕

代码

//CF522D
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>

#define LL long long
#define Lson (X<<1)
#define Rson (X<<1|1)
#define Cl(X,Y) memset((X),(Y),sizeof(X))
#define FOR(i,A,B) for(int i=A;i<=B;i++)
#define BOR(i,A,B) for(int i=A;i>=B;i--)
#define INF 0x3f3f3f3f
using namespace std;
const int MaxN=5e5+10;

int Num[MaxN],Last[MaxN],Cop[MaxN];
int Total,Test;
struct Node {
    int Left,Right,ID;
    friend bool operator < (Node A,Node B)
    { return ((A.Right<B.Right) || (A.Right==B.Right && A.Left<B.Left)); }
}Ask[MaxN];
int Tree[MaxN<<2],Ans[MaxN];

inline void File() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}

inline void Push_up(int X) { Tree[X]=min(Tree[Lson],Tree[Rson]); }
inline void Update(int X,int L,int R,int Loc,int Temp) {
    if(L==R) { Tree[X]=Temp; return; }
    int Mid=(L+R)>>1;
    if(Loc<=Mid) Update(Lson,L,Mid,Loc,Temp);
    else Update(Rson,Mid+1,R,Loc,Temp);
    Push_up(X);
}

inline int Get(int X,int L,int R,int From,int To) {
    if(L>=From && R<=To) { return Tree[X]; }
    int Mid=(L+R)>>1,Res=INF;
    if(From<=Mid) Res=min(Res,Get(Lson,L,Mid,From,To));
    if(To>Mid) Res=min(Res,Get(Rson,Mid+1,R,From,To));
    return Res;
}

int main() {
    // File();
    scanf("%d %d",&Total,&Test);
    FOR(i,1,Total) scanf("%d",&Num[i]),Cop[i]=Num[i];
    sort(Cop+1,Cop+Total+1);
    int Size=unique(Cop+1,Cop+Total+1)-(Cop+1);
    FOR(i,1,Total) Num[i]=lower_bound(Cop+1,Cop+Size+1,Num[i])-Cop;
    int Loc=1;
    Cl(Tree,0x3f);
    FOR(i,1,Test) scanf("%d %d",&Ask[i].Left,&Ask[i].Right),Ask[i].ID=i;
    sort(Ask+1,Ask+Test+1);
    FOR(i,1,Test) {
        while(Loc<=Ask[i].Right) {
            Cop[Loc]=Last[Num[Loc]];//废物利用
            Last[Num[Loc]]=Loc;
            if(Cop[Loc]!=0) Update(1,1,Total,Cop[Loc],(Loc-Cop[Loc]));
            Loc++;
        }
        Ans[Ask[i].ID]=Get(1,1,Total,Ask[i].Left,Ask[i].Right);
    }
    FOR(i,1,Test) printf("%d\n",Ans[i]==INF ? -1 : Ans[i]);
    // fclose(stdin);
    // fclose(stdout);
    system("pause");
    return 0;
}