CF765F Souvenirs
Souvenirs
给出 \(n\) 以及一个长为 \(n\) 的序列 \(a\)。
给出 \(m\),接下来 \(m\) 组询问。每组询问给出一个 \(l,r\),你需要求出,对于 \(i,j \in [l,r]\),且满足 \(i \neq j\),\(|a_i-a_j|\) 的最小值。
\(1 \leq n \leq 10^5\),\(1 \leq m \leq 3\times 10^5\),\(0 \leq a_i \leq 10^9\)。
题解
https://www.cnblogs.com/CQzhangyu/p/8468825.html
\[a_{j'}-a_i< a_j-a_{j'}\\
2(a_{j'}-a_i)< a_j-a_i\\
\]
所以每次差会减半。
怎么找 \(a_j\) 呢?按照从大到小的顺序插入线段树然后在线段树上二分即可。
然后每个贡献可以写成点对的形式,就转化成了一个二维偏序。
时间复杂度 \(O(n\log n\log v)\)。
CO int N=1e5+10,inf=2e9;
int a[N],o[N];
namespace seg{
int s[4*N];
#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
void build(int x,int l,int r){
s[x]=inf;
if(l==r) return;
build(lc,l,mid),build(rc,mid+1,r);
}
void insert(int x,int l,int r,int p,int v){
s[x]=min(s[x],v);
if(l==r) return;
if(p<=mid) insert(lc,l,mid,p,v);
else insert(rc,mid+1,r,p,v);
}
int query(int x,int l,int r,int p,int v){
if(p<l) return 0;
if(r<=p){
if(s[x]>v) return 0;
if(l==r) return l;
if(s[rc]<=v) return query(rc,mid+1,r,p,v);
else return query(lc,l,mid,p,v);
}
if(p<=mid) return query(lc,l,mid,p,v);
int ans=query(rc,mid+1,r,p,v);
if(ans) return ans;
return query(lc,l,mid,p,v);
}
#undef lc
#undef rc
#undef mid
}
namespace bit{
int n,s[N];
void init(int n){
bit::n=n,fill(s+1,s+n+1,inf);
}
#define lowbit(x) (x&-x)
void insert(int p,int v){
for(int i=p;i;i-=lowbit(i)) s[i]=min(s[i],v);
}
int query(int p){
int ans=inf;
for(int i=p;i<=n;i+=lowbit(i)) ans=min(ans,s[i]);
return ans;
}
#undef lowbit
}
struct point {int x,y,v;} p[N*30],q[3*N];
int ans[3*N];
void solve(int n,int m){
for(int i=1;i<=n;++i) o[i]=i;
sort(o+1,o+n+1,[](int i,int j)->bool{
return a[i]!=a[j]?a[i]>a[j]:i<j; // edit 1: i<j
});
seg::build(1,1,n);
int tot=0;
for(int i=1;i<=n;++i){
seg::insert(1,1,n,o[i],a[o[i]]);
int j=seg::query(1,1,n,o[i]-1,inf-1);
if(!j) continue;
do p[++tot]={j,o[i],a[j]-a[o[i]]};
while((j=seg::query(1,1,n,j-1,(a[o[i]]+a[j]+1)/2-1)));
}
sort(p+1,p+tot+1,[](CO point&a,CO point&b)->bool{
return a.y<b.y;
});
sort(q+1,q+m+1,[](CO point&a,CO point&b)->bool{
return a.y<b.y;
});
bit::init(n);
for(int i=1,j=1;i<=tot or j<=m;){
if(j>m or (i<=tot and p[i].y<=q[j].y)){
bit::insert(p[i].x,p[i].v);
++i;
}
else{
ans[q[j].v]=min(ans[q[j].v],bit::query(q[j].x));
++j;
}
}
}
int main(){
int n=read<int>();
for(int i=1;i<=n;++i) read(a[i]);
int m=read<int>();
for(int i=1;i<=m;++i) read(q[i].x),read(q[i].y),q[i].v=i;
fill(ans+1,ans+m+1,inf);
solve(n,m);
for(int i=1;i<=n;++i) a[i]=1e9-a[i];
solve(n,m);
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}
静渊以有谋,疏通而知事。