专栏文章

题解:CF1693E Outermost Maximums

CF1693E题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min7levl
此快照首次捕获于
2025/12/01 21:52
3 个月前
此快照最后确认于
2025/12/01 21:52
3 个月前
查看原文

Sol

其实可以分别处理每个位置值的最优变化序列。不难证明总能将他们合并在一起。
考虑如何快速处理每个位置值的最优变化序列,考虑维护一个值域上的序列,序列各位维护这个数在当前位置左右两侧的出现情况共四种状态,位置移动时只需要单点修改,单次变化可以视作跳到左侧最近的为相应状态的位置,上线段树维护进出区间最小代价即可,询问时区间查一下就做完了。
值得注意的是区间信息需要维护进入节点目标状态与离开节点目标状态组合共四种情况,才可以正确合并,否则可能会有不合法的更优情况。

Code

CPP
const int N=2e5+5;

int n;
int a[N];
int cntl[N],cntr[N];

struct node{
    int cnt[2];
    ll val[2][2];
}dat[N<<2];
node merge(node a,node b){
    node c;
    c.cnt[0]=a.cnt[0]+b.cnt[0],c.cnt[1]=a.cnt[1]+b.cnt[1];
    rep(i,0,1)rep(j,0,1){
        if(b.cnt[i]){
            c.val[i][j]=INF;
            if(a.cnt[0])chmin(c.val[i][j],b.val[i][0]+a.val[0][j]);
            if(a.cnt[1])chmin(c.val[i][j],b.val[i][1]+a.val[1][j]);
            if(!a.cnt[j])chmin(c.val[i][j],b.val[i][j]);
        }else c.val[i][j]=a.val[i][j];
    }
    return c;
}
void build(int x=1,int l=1,int r=n){
    if(l==r){
        dat[x].cnt[0]=cntl[l];
        dat[x].cnt[1]=cntr[l];
        dat[x].val[0][0]=dat[x].val[0][1]=!!cntl[l];
        dat[x].val[1][0]=dat[x].val[1][1]=!!cntr[l];
        return;
    }
    int m=l+r>>1;
    build(x<<1,l,m),build(x<<1|1,m+1,r);
    dat[x]=merge(dat[x<<1],dat[x<<1|1]);
}
void update(int k,int x=1,int l=1,int r=n){
    if(!k)return;
    if(l==r){
        dat[x].cnt[0]=cntl[l];
        dat[x].cnt[1]=cntr[l];
        dat[x].val[0][0]=dat[x].val[0][1]=!!cntl[l];
        dat[x].val[1][0]=dat[x].val[1][1]=!!cntr[l];
        return;
    }
    int m=l+r>>1;
    if(k<=m)update(k,x<<1,l,m);
    else update(k,x<<1|1,m+1,r);
    dat[x]=merge(dat[x<<1],dat[x<<1|1]);
}
node query(int lq,int rq,int x=1,int l=1,int r=n){
    if(lq>rq)return node();
    if(lq<=l&&r<=rq)return dat[x];
    int m=l+r>>1;
    if(rq<=m)return query(lq,rq,x<<1,l,m);
    if(m<lq)return query(lq,rq,x<<1|1,m+1,r);
    return merge(query(lq,rq,x<<1,l,m),query(lq,rq,x<<1|1,m+1,r));
}

inline void Main(){
	cin>>n;
    rep(i,1,n)cin>>a[i],++cntr[a[i]];
    build();
    ll ans=0;
    rep(i,1,n){
        --cntr[a[i]],++cntl[a[i-1]];
        update(a[i]),update(a[i-1]);
        if(!a[i])continue;
        node res=query(1,a[i]-1);
        ans+=min({res.val[0][0],res.val[0][1],res.val[1][0],res.val[1][1]})+1;
    }
    put(ans);
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...