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

  

posted @ 2020-07-17 14:01  EM-LGH  阅读(150)  评论(0编辑  收藏  举报