最多存在个数对会贡献答案
就是每个数和前面第一个和自己相同的数,把下标记作
那么想象一下,现在要统计的最短相同数对距离
我们可以直接对所有的
投射到线段树上去
线段树上的下标就是,值就是
这样我们查询的最小值,查到的所有
的
都属于,而
由于是下标,所以也肯定满足
由于每个区间只需要的数插入,所以按照
端点排序
这样每个点只需要插入一次,非常快
非常巧妙的思路
关于找前一个相同的数,可以用,也可以离散化
#include <bits/stdc++.h>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn=2e6+10;
const int inf=1e9;
int a[maxn],b[maxn],n,m,ans[maxn];
map<int,int>mp;
struct p{
int l,r,id;
bool operator < (const p&tmp ) const
{ return r<tmp.r; }
}f[maxn]; int top=1;
void update(int rt,int l,int r,int u,int val)
{
if( l==r&&l==u ){ a[rt]=val; return; }
if( r<u||l>u ) return;
update(lson,u,val); update(rson,u,val);
a[rt] = min( a[ls],a[rs] );
}
int ask(int rt,int l,int r,int L,int R)
{
if( l>=L&&r<=R ) return a[rt];
if( r<L||l>R ) return inf;
return min( ask(lson,L,R),ask(rson,L,R) );
}
int main()
{
cin >> n >> m;
for(int i=1;i<=4*n;i++) a[i]=inf;//线段树初始化
for(int i=1;i<=n;i++) cin >> b[i];
for(int i=1;i<=m;i++) scanf("%d%d",&f[i].l,&f[i].r),f[i].id=i;
sort(f+1,f+1+m);
for(int i=1;i<=n;i++)
{
if( mp[b[i]] ) update(1,1,n,mp[b[i]],i-mp[b[i]]);
while( top<=m&&i==f[top].r )
ans[f[top].id]=ask(1,1,n,f[top].l,f[top].r),top++;
mp[b[i]]=i;
}
for(int i=1;i<=m;i++)
cout << ( ans[i]==inf?-1:ans[i] ) << '\n';
}
京公网安备 11010502036488号