CF765F Souvenirs 主席树+复杂度分析
这题看上去没有任何思路,不妨考虑暴力:
先求对于 $i \leqslant j$ 且 $a_{i} > a_{j}$ 的 $min(a_{i}-a_{j}).$.
对于 $a_{i} < a_{j}$ 的情况将序列中的数乘上-1再求一遍即可.
考虑将询问离线,枚举右端点,那么 $i$ 能贡献到 $a_{j}>a_{i}$.
$a_{j}$ 的级别是 $O(n)$ 的,整体复杂度是 $O(n^2)$.
$i$ 并不会对所有的 $a_{j}>a_{i}$ 都起贡献.
比如我们更新的一个 $j$ 满足 $a_{j}>a_{i}$,然后下一个大于 $a_{i}$ 的是 $j'$.
那么 $j'$ 有贡献当且仅当 $a_{j'}<a_{j}$ 且 $a_{j}-a_{j'}>a_{j'}-a_{i}$.
满足 $2a_{j'}<a_{j}+a_{i}$.
然后这样的 $a_{j'}$ 最多只有 $\log 10^9$,所以对于一个 $i$ 来说我们只需更新 $\log 10^9$ 个.
然后找 $j'$ 可以用主席树,维护过程比较复杂,时间复杂度为 $O(n \log n \log 10^9)$.
code:
#include <vector> #include <cstdio> #include <cstring> #include <algorithm> #define N 300009 #define pb push_back #define ll long long #define inf 2000000000 #define INF 1000000000 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,tot; int a[N],ans[N],c[N],A[N],rt[N]; struct data { int ls,rs,sum,ma; data() { ls=rs=sum=ma=0; } }s[N*30]; struct que { int l,id; que(int l=0,int id=0):l(l),id(id){} }; vector<que>q[N]; int lowbit(int x) { return x&(-x); } void upd(int x,int v) { for(int i=x;i;i-=lowbit(i)) c[i]=min(c[i],v); } int ask(int x) { int re=inf; for(int i=x;i<=n;i+=lowbit(i)) re=min(re,c[i]); return re; } int update(int x,int l,int r,int p,int v) { int now=++tot; s[now]=s[x]; s[now].sum+=1; s[now].ma=max(s[now].ma,v); if(l==r) return now; int mid=(l+r)>>1; if(p<=mid) { s[now].ls=update(s[x].ls,l,mid,p,v); } else { s[now].rs=update(s[x].rs,mid+1,r,p,v); } return now; } int get_rank(int x,int l,int r,int p) { if(!x) return 0; if(l==r) { return p>=l?s[x].sum:0; } int mid=(l+r)>>1; if(p<=mid) { return get_rank(s[x].ls,l,mid,p); } else { return s[s[x].ls].sum+get_rank(s[x].rs,mid+1,r,p); } } int get_mx(int x,int l,int r,int L,int R) { if(!x) return -INF; if(l>=L&&r<=R) return s[x].ma; int mid=(l+r)>>1,re=-INF; if(L<=mid) re=max(re,get_mx(s[x].ls,l,mid,L,R)); if(R>mid) re=max(re,get_mx(s[x].rs,mid+1,r,L,R)); return re; } int get_num(int x,int l,int r,int kth) { if(!x) return -INF; if(l==r) { return l; } int mid=(l+r)>>1,re=s[s[x].ls].sum; if(kth<=re) { return get_num(s[x].ls,l,mid,kth); } else { return get_num(s[x].rs,mid+1,r,kth-re); } } void sol() { for(int i=1;i<=n;++i) A[i]=a[i]; for(int i=0;i<N;++i) c[i]=inf; for(int i=1;i<=n;++i) rt[i]=0; for(int i=1;i<=tot;++i) s[i]=data(); tot=0,sort(A+1,A+1+n); for(int i=1;i<=n;++i) { int v=INF,r=i-1,flag=0; while(r>=1) { int ra=get_rank(rt[r],-INF,INF,a[i]-1); int z=get_num(rt[r],-INF,INF,ra+1); if(z<a[i]||(flag&&(z>=v))) break; int cur=get_mx(rt[r],-INF,INF,z,v); upd(cur,a[cur]-a[i]); r=cur-1,v=(a[cur]+a[i])>>1,flag=1; if(((a[cur]+a[i])%2)&&v<0) ++v; } rt[i]=update(rt[i-1],-INF,INF,a[i],i); for(int j=0;j<q[i].size();++j) { ans[q[i][j].id]=min(ans[q[i][j].id],ask(q[i][j].l)); } } } int main() { // setIO("input"); scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); scanf("%d",&m); int x,y,z; for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); q[y].pb(que(x,i)); ans[i]=inf; } sol(); for(int i=1;i<=n;++i) a[i]=-a[i]; sol(); for(int i=1;i<=m;++i) { printf("%d\n",ans[i]); } return 0; }