zoukankan      html  css  js  c++  java
  • CF765F Souvenirs

    CF765F Souvenirs 

    【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*
    */
  • 相关阅读:
    分组PARTITION BY及游标CURSOR的用法
    dotnet core 3.1+consul 学习(1)
    常用状态码
    docker 安装consul以及部署consul集群
    泛型
    redis面试题(1)
    asp net core 3.1启动过程源码解读
    .net core 2.x到3.x变化 -> Endpoint Routing
    jwt登录验证逻辑
    .Net Core3.1+Jenkins+Docker+Git实现自动化部署
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10760507.html
Copyright © 2011-2022 走看看