题解 AT3673 【[ARC085D] NRE】

· · 题解

upd :修改了一些笔误

模拟赛见到了这道题并意外地做了出来。赛时觉得好像是我看到过但没去做的一道 ARC 的题,赛后发现还真的是 ARC 的原题。这题挺有意思的,写篇题解纪念一下。

思路

\min{f_j+r_i-l_i+1-2(sum_{r_i}-sum_{l_i-1})},S_i\cap S_j=\varnothing\\ \min{f_j+r_i-r_j-2(sum_{r_i}-sum_{r_j})},S_i\cap S_j\neq\varnothing\ \text{且}\ S_i\subsetneq S_j\\ \min{f_j},S_i\subseteq S_j \end{cases}

代码

#include<bits/stdc++.h>
#define I using
#define love namespace
#define Elaina std
I love Elaina;
const int N=200010;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int n,m,a[N],sum[N],f[N],ans,res;
struct qry{
    int l,r;
    bool operator<(const qry &rhs)const{
        return (l!=rhs.l)?l<rhs.l:r<rhs.r;
    }
}qwq[N];
namespace AyaseEli{
    #define ls(k) (k<<1)
    #define rs(k) (k<<1|1)
    struct node{
        int minn,l,r;
    }tree[2][N<<2];
    void pushup(node *tree,int k){
        tree[k].minn=min(tree[ls(k)].minn,tree[rs(k)].minn);
    }
    void build(node *tree,int k,int l,int r){
        tree[k].l=l,tree[k].r=r,tree[k].minn=0x3f3f3f3f;
        if(l==r)return;
        int mid=(l+r)/2;
        build(tree,ls(k),l,mid),build(tree,rs(k),mid+1,r);
        pushup(tree,k);
    }
    void modify(node *tree,int k,int q,int v){
        if(tree[k].l==tree[k].r){
            tree[k].minn=v;
            return;
        }
        int mid=(tree[k].l+tree[k].r)/2;
        if(q<=mid)modify(tree,ls(k),q,v);
        else modify(tree,rs(k),q,v);
        pushup(tree,k);
    }
    int query(node *tree,int k,int ql,int qr){
        int res=0x3f3f3f3f;
        if(ql<=tree[k].l&&tree[k].r<=qr)return tree[k].minn;
        int mid=(tree[k].l+tree[k].r)/2;
        if(ql<=mid)res=min(res,query(tree,ls(k),ql,qr));
        if(mid<qr)res=min(res,query(tree,rs(k),ql,qr));
        return res;
    }
}
I love AyaseEli;
int main(){
    memset(f,0x3f,sizeof(f));
    n=read();
    build(tree[0],1,1,n),build(tree[1],1,1,n);
    for(int i=1;i<=n;i++)a[i]=read(),sum[i]=sum[i-1]+a[i];
    ans=sum[n];
    m=read();
    for(int i=1;i<=m;i++)qwq[i]=(qry){read(),read()};
    sort(qwq+1,qwq+m+1);
    for(int i=1;i<=m;i++){
        f[i]=sum[n]+qwq[i].r-qwq[i].l+1-2*(sum[qwq[i].r]-sum[qwq[i].l-1]);
        if(qwq[i].l!=1)f[i]=min(f[i],query(tree[0],1,1,qwq[i].l-1)+qwq[i].r-qwq[i].l+1-2*(sum[qwq[i].r]-sum[qwq[i].l-1]));
        f[i]=min(f[i],query(tree[1],1,qwq[i].l,qwq[i].r)+qwq[i].r-2*sum[qwq[i].r]);
        modify(tree[0],1,qwq[i].r,f[i]),modify(tree[1],1,qwq[i].r,f[i]-qwq[i].r+2*sum[qwq[i].r]);
        ans=min(ans,f[i]);
    }
    printf("%d",ans);
    return 0;
}

祝各位大神们 NOI 加油!