考虑离线,我们从左往右扫,对于现在的点i,我们先找到离i最近的j使得a[j]>=a[i],然后我们可以知道询问左区间在1~j的询问的答案小于等于a[j]-a[i],我们可以用线段树更新答案,然后还可能存在f<j使得a[f]>=a[i],a[f]-a[i]<=a[j]-a[f],因为a[j]-a[f]已经更新进线段树,所以a[f]<=(a[j]+a[i)/2,我们只要找到里j最近的f即可,然后一直做先去,因为我们发先每次都是除2,所以只要做log(a[i])步就行,然后找的过程也只要离散化a[i]然后开一个查询位置的最大值的线段树即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100005;
struct pi{
int le,ri;
int ma;
}pp[2][maxn<<2];
void build(int u,int tot,int l,int r){
pp[u][tot].le=l;
pp[u][tot].ri=r;
if(u==1) pp[u][tot].ma=1000000000;
else pp[u][tot].ma=0;
if(l==r) return;
build(u,2*tot,l,(l+r)/2);
build(u,2*tot+1,(l+r)/2+1,r);
}
void merg(int tot,int x,int p){
pp[0][tot].ma=max(pp[0][tot].ma,p);
if(pp[0][tot].le==pp[0][tot].ri) return;
int mid=(pp[0][tot].le+pp[0][tot].ri)/2;
if(x<=mid) merg(2*tot,x,p);
else merg(2*tot+1,x,p);
}
void merg1(int tot,int l,int r,int p){
if(pp[1][tot].le>=l&&pp[1][tot].ri<=r){
pp[1][tot].ma=min(pp[1][tot].ma,p);
return;
}
int mid=(pp[1][tot].le+pp[1][tot].ri)/2;
if(l<=mid) merg1(2*tot,l,r,p);
if(r>mid) merg1(2*tot+1,l,r,p);
}
int query(int tot,int l,int r){
if(pp[0][tot].le>=l&&pp[0][tot].ri<=r) return pp[0][tot].ma;
int s=0;
int mid=(pp[0][tot].le+pp[0][tot].ri)/2;
if(l<=mid) s=max(s,query(2*tot,l,r));
if(r>mid) s=max(s,query(2*tot+1,l,r));
return s;
}
int query1(int tot,int x){
if(pp[1][tot].le==pp[1][tot].ri) return pp[1][tot].ma;
int s=pp[1][tot].ma;
int mid=(pp[1][tot].le+pp[1][tot].ri)/2;
if(x<=mid) s=min(s,query1(2*tot,x));
else s=min(s,query1(2*tot+1,x));
return s;
}
struct in{
int l,r;
int id;
}re[maxn*3];
int a[maxn];
int b[maxn];
int ans[maxn*3];
vector<in>g[maxn];
void solve(int n,int m){
for(int i=0;i<2;i++) build(i,1,1,n);
for(int i=1;i<=n;i++) g[i].clear();
for(int i=0;i<m;i++){
g[re[i].r].push_back(re[i]);
}
for(int i=1;i<=n;i++){
if(i!=1){
int w=query(1,a[i],n);
if(w!=0){
merg1(1,1,w,b[a[w]]-b[a[i]]);
int r=a[w];
while(1){
int no=(b[a[i]]+b[r])/2;
int w=lower_bound(b+1,b+1+n,no)-b;
if(b[w]!=no) w--;
if(w<1) break;
if(w==r||w<a[i]) break;
int nn=query(1,a[i],w);
if(nn==0) break;
merg1(1,1,nn,b[a[nn]]-b[a[i]]);
r=a[nn];
}
}
}
merg(1,a[i],i);
for(in v:g[i]){
ans[v.id]=min(ans[v.id],query1(1,v.l));
}
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+n,a[i])-b;
int m;
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d",&re[i].l,&re[i].r);
re[i].id=i;
ans[i]=1000000000;
}
solve(n,m);
for(int i=0;i<m;i++){
int w=re[i].l;
re[i].l=n-re[i].r+1;
re[i].r=n-w+1;
}
for(int i=1;i<=n/2;i++){
swap(a[i],a[n-i+1]);
}
solve(n,m);
for(int i=0;i<m;i++) printf("%d\n",ans[i]);
}