【CF765F】Souvenirs 主席树 - CQzhangyu - 博客园
其实不用主席树
感觉像是离线问题
但是不能支持差分。分治又处理不了
考虑按照右端点排序,线段树维护左端点为i的时候的答案
然后trick一下,把求ansl,变成求min(ansl....ansr),这样可以少更新很多
先把|ai-aj|变成j<i,aj>=ai这样找,然后再反过来做一次。
新加入的a[i],找之前第一个大于a[i]的a[pos],(pos是所在位置)
在pos位置更新答案。
对于k<pos,若a[k]>=a[pos],显然再和a[i]做贡献没有意义了。取到ansk一定能取到anspos
设mid=(a[pos]+a[i])/2,发现,对于k<pos,且a[k]>mid,a[k]和a[pos]做贡献一定更优(这在反过来的时候会考虑到),并且取到ansk一定能取到和pos做的贡献
所以只用考虑k<=mid,规模每次/2,log(max{ai})次logn
找pos,可以用动态开点线段树,每次找权值范围内最晚出现的。
复杂度:O(nlognlogai)
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Miracle{ const int N=4e5+5; const int inf=0x3f3f3f3f; int n,m; int ans[N]; int a[N]; struct que{ int l,r,id; }q[N]; bool cmp1(que a,que b){ return a.r<b.r; } bool cmp2(que a,que b){ return a.l>b.l; } #define mid ((l+r)>>1) namespace tr1{ int rt; struct node{ int ls,rs; int tim; node(){ tim=0; } }t[N*40]; int tot; void pushup(int x){ t[x].tim=max(t[t[x].ls].tim,t[t[x].rs].tim); } int fin(int x,int l,int r,int L,int R){ if(L>R) return 0; if(!x) return 0; if(L<=l&&r<=R){ if(l==r) return t[x].tim; if(t[t[x].ls].tim>t[t[x].rs].tim) return fin(t[x].ls,l,mid,L,R); else return fin(t[x].rs,mid+1,r,L,R); } if(R<=mid) return fin(t[x].ls,l,mid,L,R); if(L>mid) return fin(t[x].rs,mid+1,r,L,R); return max(fin(t[x].ls,l,mid,L,R),fin(t[x].rs,mid+1,r,L,R)); } void chan(int &x,int l,int r,int p,int ti){ if(!x) x=++tot; if(l==r){ t[x].tim=max(t[x].tim,ti);return; } if(p<=mid) chan(t[x].ls,l,mid,p,ti); else chan(t[x].rs,mid+1,r,p,ti); pushup(x); } void init(){ t[0].tim=0; tot=0; } void clear(){ for(reg i=1;i<=tot;++i){ t[i].ls=t[i].rs=0; t[i].tim=0; } tot=0;rt=0; } } namespace tr2{ #define ls (x<<1) #define rs (x<<1|1) int ans[4*N]; void build(int x,int l,int r){ if(l==r){ ans[x]=inf;return ; } ans[x]=inf; build(x<<1,l,mid);build(x<<1|1,mid+1,r); } void pushup(int x){ ans[x]=min(ans[ls],ans[rs]); } void upda(int x,int l,int r,int p,int c){ if(l==r){ ans[x]=min(ans[x],c);return; } if(p<=mid) upda(ls,l,mid,p,c); else upda(rs,mid+1,r,p,c); pushup(x); } int query(int x,int l,int r,int L,int R){ if(L<=l&&r<=R) return ans[x]; if(R<=mid) return query(ls,l,mid,L,R); if(L>mid) return query(rs,mid+1,r,L,R); return min(query(ls,l,mid,L,R),query(rs,mid+1,r,L,R)); } void clear(){ memset(ans,0x3f,sizeof ans); } } int main(){ // cout<<" 23333 "<<endl; rd(n); int lim=0; for(reg i=1;i<=n;++i) rd(a[i]),lim=max(lim,a[i]); // cout<<" after rd "<<lim<<endl; rd(m); for(reg i=1;i<=m;++i){ rd(q[i].l);rd(q[i].r);q[i].id=i; } // cout<<" after rd "<<endl; memset(ans,0x3f,sizeof ans); sort(q+1,q+m+1,cmp1); int ptr=1; // cout<<" sort1 "<<endl; tr2::build(1,1,n); tr1::init(); // cout<<" built "<<endl; for(reg i=1;i<=n;++i){ // cout<<" ii "<<i<<" ptr "<<ptr<<endl; if(i!=1){ int pos=tr1::fin(tr1::rt,0,lim,a[i],lim); while(pos){ // cout<<" pos "<<pos<<endl; tr2::upda(1,1,n,pos,a[pos]-a[i]); // cout<<" after tr2 upda "<<endl; pos=tr1::fin(tr1::rt,0,lim,a[i],min(a[pos]-1,(a[pos]+a[i])/2)); } } // cout<<" over udpa "<<endl; while(ptr<=m&&q[ptr].r==i){ ans[q[ptr].id]=min(ans[q[ptr].id],tr2::query(1,1,n,q[ptr].l,i)); ++ptr; } tr1::chan(tr1::rt,0,lim,a[i],i); } // cout<<" turn1 "<<endl; tr2::clear(); tr1::clear(); tr2::build(1,1,n); sort(q+1,q+m+1,cmp2); ptr=1; // cout<<" st2 "<<endl; for(reg i=n;i>=1;--i){ if(i!=n){ int pos=tr1::fin(tr1::rt,0,lim,a[i],lim); while(pos){ pos=n-pos+1; tr2::upda(1,1,n,pos,a[pos]-a[i]); pos=tr1::fin(tr1::rt,0,lim,a[i],min(a[pos]-1,(a[pos]+a[i])/2)); } } while(ptr<=m&&q[ptr].l==i){ ans[q[ptr].id]=min(ans[q[ptr].id],tr2::query(1,1,n,i,q[ptr].r)); ++ptr; } tr1::chan(tr1::rt,0,lim,a[i],n-i+1); } // cout<<" turn2 "<<endl; // return 0; for(reg i=1;i<=m;++i){ printf("%d ",ans[i]); } return 0; } } signed main(){ // freopen("data.in","r",stdin); // freopen("my.out","w",stdout); Miracle::main(); return 0; } /* Author: *Miracle* */