[2020.11.13]CF765F Souvenirs
阿新 • • 發佈:2020-11-13
題意
給出一個長度為\(n\)的序列\(a\),\(q\)組詢問,每次詢問一個區間\(l,r\),求\(|a_i-a_j|\)的最小值,其中\(i\ne j\),\(l\le i,j\le r\)。
題解
考慮離線,先考慮\(i<j,a_i\le 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\)
這也就意味著\(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\n",prt[i]); return 0; }