AT3673 [ARC085D] NRE 题解

AT3673 [ARC085D] NRE 题解

Problem

​ 给定一个全为\(0\)的数组\(A\),给一个数组\(B\)和\(m\)个操作,每个操作将数组\(A\)指定区间改成\(1\),问合理选择部分操作后使得两个数组的\(\sum[A_i \neq B_i]\)最小。

Solution

​ 考虑把这个式子变形一下:

\[\sum[A_i \neq B_i] \\ \rightarrow \sum[A_i=0][B_i=1]+\sum[A_i=1][B_i=0] \\ \rightarrow \sum[A_i=0]+\sum[B_i=0]([A_i=1]-[A_i=0]) \]

​ 第一项\([A_i=0]\)是个定值,\(([A_i=1]-[A_i=0])\)也只和\(A\)有关,所以现在要考虑的只有\([B_i=0]\)。

​ 考虑DP,设\(f_i\)表示前\(i\)个中上式的最小值。首先可以从\(f_i\)转移到\(f_{i+1}\),表示不选以\(i\)为左端点的区间,要么可以转移到右端点

Code

#include<bits/stdc++.h>
using namespace std;

vector<int>L[200005];

int n,m,Ans;

int A[200005];

struct Segment_Tree{

    #define ls k<<1|0
    #define rs k<<1|1
    #define inf 0x3f3f3f3f

    int tag[800005],Min[800005];

    inline void Pushup(int k){
        Min[k]=min(Min[ls],Min[rs]);
    }

    inline void Pushdown(int k){
        if(tag[k]){
            tag[ls]+=tag[k];
            tag[rs]+=tag[k];
            Min[ls]+=tag[k];
            Min[rs]+=tag[k];
            tag[k];
        }
        return;
    }

    void Initialize(){
        memset(Min,0x3f,sizeof Min);
    }

    void Insert(int k,int l,int r,int pos,int val){
        if(l==r){
            Min[k]=min(Min[k],val);
            return;
        }
        Pushdown(k);
        int mid=l+r>>1;
        if(pos<=mid)
            Insert(ls,l,mid+0,pos,val);
        else
            Insert(rs,mid+1,r,pos,val);
        return Pushup(k);
    }

    void Change(int k,int l,int r,int wl,int wr,int val){
        if(wl> r||l> wr)
            return;
        if(wl<=l&&r<=wr){
            tag[k]+=val;
            Min[k]+=val;
            return;
        }
        Pushdown(k);
        int mid=l+r>>1;
        Change(ls,l,mid+0,wl,wr,val);
        Change(rs,mid+1,r,wl,wr,val);
        return Pushup(k);
    }

    int query(int k,int l,int r,int wl,int wr){
        if(wl> l||l> wr)    
            return inf;
        if(wl<=l&&r<=wr)
            return Min[k];
        Pushdown(k);
        int res=inf,mid=l+r>>1;
        res=min(res,query(ls,l,mid+0,wl,wr));
        res=min(res,query(rs,mid+1,r,wl,wr));
        return res;
    }

    #undef ls
    #undef rs
    #undef inf

}T;

inline 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<<1)+(x<<3)+ch-'0';
       ch=getchar();
    }
    return x*f;
}

int main(){
    
    n=read();

    for(register int i=1;i<=n;++i)
        A[i]=read();
    
    m=read();

    for(register int i=1;i<=m;++i){
        int l=read();
        int r=read();   
        L[l].push_back(r);
    }

    T.Initialize();

    T.Insert(1,0,n,0,0);

    for(register int i=1;i<=n;++i){
        int N=L[i].size();
        for(register int k=0;k<N;++k){
            int Min=T.query(1,0,n,0,L[i][k]);
            T.Insert(1,0,n,L[i][k],Min);
        }
        T.Change(1,0,n,0,i-1,A[i]?+1:-1);
        Ans+=(A[i]==0);
    }

    printf("%d\n",Ans+T.query(1,0,n,0,n));

    return 0;
}
上一篇:gcc/g++ 安全编码


下一篇:测试文章啊