CF765F Souvenirs 题解
题目询问在区间\([l,r]\)内满足\(l \le i < j \le r\)这一条件的最小的\(|a_i-a_j|\)。
首先有一个想法是离线下来询问,然后对于每一个\(i\)找住\(j\)满足\(j<i\)且\(a_j>a_i\),(绝对值把\(a_i\)变为\(1e9-a_i\),也就是反过来即可)。
但是找到所有\(j\)复杂度过高,不可以接受,我们考虑那些\(j\)可以对答案产生影响。
假设我们现在处理的点是\(i\),刚修改过的点是\(j\),我们考虑\(k<i\)且\(a_k<a_j,a_k>=a_i\)。
如果要\(a_k-a_i\)最优,需要保证\(a_k-a_i<a_j-a_k\),移向得\(a_k-a_i < \frac{1}{2} (a_j-a_i)\)
每次值域缩小一半,复杂度为\(n \log2(n)^2\)
代码:
#include <bits/stdc++.h>
#define int long long
#define mid ((l+r)/2)
using namespace std;
const int maxn=1e5+10;
int n,ans[maxn<<2],a[maxn],pos,jie=1e9,idd,m,x,y,rt,C[maxn];
struct edge{
int ls;
int rs;
int mx;
}tree[maxn<<5];
vector<pair<int,int> >xun[maxn];
int lowbit(int q){
return q&(-q);
}
void add(int q,int w){
for(int i=q;i;i-=lowbit(i)){
C[i]=min(C[i],w);
}
return;
}
int query(int q){
int mn=jie;
for(int i=q;i<=n;i+=lowbit(i)){
mn=min(mn,C[i]);
}
return mn;
}
void add(int &id,int l,int r,int q,int w){
if(!id){
idd++;
id=idd;
}
if(l==r){
tree[id].mx=w;
return;
}
if(q<=mid){
add(tree[id].ls,l,mid,q,w);
}
else{
add(tree[id].rs,mid+1,r,q,w);
}
tree[id].mx=max(tree[tree[id].ls].mx,tree[tree[id].rs].mx);
return;
}
int query(int id,int l,int r,int q,int w){
if(q>w){
return 0;
}
if(q<=l&&r<=w){
return tree[id].mx;
}
if(w<=mid){
return query(tree[id].ls,l,mid,q,w);
}
else if(q>mid){
return query(tree[id].rs,mid+1,r,q,w);
}
else{
return max(query(tree[id].ls,l,mid,q,w),query(tree[id].rs,mid+1,r,q,w));
}
}
void solve(){
memset(C,0x3f,sizeof(C));
for(int i=1;i<=idd;i++){
tree[i].ls=0;
tree[i].rs=0;
tree[i].mx=0;
}
idd=0;
rt=0;
for(int i=1;i<=n;i++){
pos=query(rt,0,jie,a[i],jie);
while(pos){
add(pos,a[pos]-a[i]);
pos=query(rt,0,jie,a[i],a[i]+(a[pos]-a[i]+1)/2-1);
}
add(rt,0,jie,a[i],i);
for(int j=0;j<xun[i].size();j++){
ans[xun[i][j].second]=min(ans[xun[i][j].second],query(xun[i][j].first));
}
}
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cin>>m;
for(int i=1;i<=m;i++){
cin>>x>>y;
xun[y].push_back({x,i});
ans[i]=jie;
}
solve();
for(int i=1;i<=n;i++){
a[i]=jie-a[i];
}
solve();
for(int i=1;i<=m;i++){
cout<<ans[i]<<'\n';
}
return 0;
}
浙公网安备 33010602011771号