首页 > 其他 > 详细

CF765F Souvenirs

时间:2019-04-24 10:32:27      阅读:209      评论:0      收藏:0      [点我收藏+]

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(\n);}

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\n",ans[i]);
    }
    return 0;
}

}
signed main(){
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
*/

 

CF765F Souvenirs

原文:https://www.cnblogs.com/Miracevin/p/10760507.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!