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;
}

浙公网安备 33010602011771号