题意
给出一个长度为(n)的序列(a),(q)组询问,每次询问一个区间(l,r),求(|a_i-a_j|)的最小值,其中(i e j),(lle i,jle r)。
题解
考虑离线,先考虑(i<j,a_ile a_j)的情况,然后把序列翻转考虑另一种情况。
那么,我们枚举(j),考虑所有可能成为答案的(i),设为(i_1,i_2,dots,i_k),其中(i_i>i_2>i_3...>i_k),且(a_{i_1}<a_{i_2}<a_{i_3}<dots<a_{i_k})。
首先,(i_1)是(j)前面第一个小于等于(a_j)的数。然后注意到如果(a_j-a_{i_x})要想成为答案必须要比(a_{i_x}-a_{i_{x-1}})要小,即(a_j-a_{i_x}<a_{i_x}-a_{i_{x-1}})变换得到(2(a_j-a_{i_x})<a_j-a_{i_{x-1}})
这也就意味着(k)是(O(log))级别的。使用主席树找到所有可能作为答案的((i,j))即可。
然后就是从前往后枚举,树状数组维护后缀(min)得到答案。
code:
#include<bits/stdc++.h>
#define ci const int&
using namespace std;
struct Query{
int p,*pos;
};
struct Val{
int v,*pos;
}ar[100010];
struct node{
int l,r,lc,rc,mx;
}t[2000010];
int n,Q,a[100010],rt[100010],cnt,ql[300010],qr[300010],prt[300010],num,mp[100010],tmp,bm[100010];
vector<Query>qi[100010];
void Build0(int&x,ci l,ci r){
x=++cnt,t[x].l=l,t[x].r=r,t[x].mx=0;
if(l==r)return(void)(t[x].lc=t[x].rc=0);
int mid=l+r>>1;
Build0(t[x].lc,l,mid),Build0(t[x].rc,mid+1,r);
}
void Build(ci lx,int&x,ci id,ci val){
if(t[lx].l>id||t[lx].r<id)return(void)(x=lx);
t[x=++cnt].l=t[lx].l,t[x].r=t[lx].r,t[x].mx=val;
if(t[x].l==t[x].r)return(void)(t[x].lc=t[x].rc=0);
Build(t[lx].lc,t[x].lc,id,val),Build(t[lx].rc,t[x].rc,id,val);
}
int Find(ci x,ci l,ci r){
if(r<t[x].l||t[x].r<l)return 0;
if(l<=t[x].l&&t[x].r<=r)return t[x].mx;
return max(Find(t[x].lc,l,r),Find(t[x].rc,l,r));
}
bool cmp(Val x,Val y){
return x.v<y.v;
}
void Ins(int x,ci v){
x=n-x+1;
while(x<=n)bm[x]=min(bm[x],v),x+=(x&-x);
}
int Que(int x){
x=n-x+1;
int ret=1e9;
while(x)ret=min(ret,bm[x]),x-=(x&-x);
return ret;
}
int Get(ci x){
int l=1,r=num,mid;
while(l<r)mid=l+r>>1,mp[mid]>=x?r=mid:l=mid+1;
return l;
}
void Solve(){
cnt=0,Build0(rt[0],1,num);
for(int i=1;i<=n;++i)Build(rt[i-1],rt[i],a[i],i),bm[i]=1e9;
for(int i=1;i<=n;++i){
tmp=Find(rt[i-1],1,a[i]);
while(tmp){
Ins(tmp,mp[a[i]]-mp[a[tmp]]);
if(a[i]==a[tmp])break;
tmp=Find(rt[tmp-1],Get(mp[a[i]]-(mp[a[i]]-mp[a[tmp]]-1>>1)),a[i]);
}
for(int j=0;j<qi[i].size();++j)(*qi[i][j].pos)=min(*qi[i][j].pos,Que(qi[i][j].p));
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&ar[i].v),ar[i].pos=&a[i];
sort(ar+1,ar+n+1,cmp),ar[0].v=-1;
for(int i=1;i<=n;++i)num+=(ar[i].v!=ar[i-1].v),mp[num]=ar[i].v,(*ar[i].pos)=num;
scanf("%d",&Q);
for(int i=1;i<=Q;++i)scanf("%d%d",&ql[i],&qr[i]),prt[i]=1e9,qi[qr[i]].push_back((Query){ql[i],&prt[i]});
Solve();
for(int i=1;i<n-i+1;++i)swap(a[i],a[n-i+1]);
for(int i=1;i<=n;++i)vector<Query>().swap(qi[i]);
for(int i=1;i<=Q;++i)qi[n-ql[i]+1].push_back((Query){n-qr[i]+1,&prt[i]});
Solve();
for(int i=1;i<=Q;++i)printf("%d
",prt[i]);
return 0;
}