zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);   
        }       
        return 0; 
    } 
    

      

  • 相关阅读:
    【转】JMeter学习(二十七)Jmeter常见问题
    【转】JMeter学习(二十三)关联
    【转】 JMeter学习(二十四)linux启动jmeter,执行./jmeter.sh报错解决方法
    【转】 JMeter学习(十九)JMeter测试MongoDB
    【转】 JMeter学习(二十)JMeter处理Cookie与Session
    【转】JMeter学习(十七)JMeter测试Java
    【转】JMeter学习(十八)JMeter测试Java(二)
    【转】 JMeter学习(十六)JMeter函数学习
    【转】JMeter学习(十四)JMeter监控Tomcat性能
    【转】JMeter学习(十三)分布式部署
  • 原文地址:https://www.cnblogs.com/guangheli/p/13329600.html
Copyright © 2011-2022 走看看