【好题】线段树优化dp——cf1334F

/*
用dp[i][j]来表示a[i]将要匹配b[j]时的代价
如果a[i]没有对应的b[x]
    如果p[i]<=0,直接将这位丢掉,dp[i][j]=dp[i-1][j]+p[i]
    如果p[i]>0, 那么这位能不丢就不丢,
        对于所有的b[j]>a[i],a[i]不丢掉是不会影响第j位的匹配的,dp[i][j]=dp[i-1][j] 
        对于所有b[j]<=a[i],a[i]必须丢掉,所以 dp[i][j]=dp[i-1][j]+p[i]
如果a[i]对应了b[x]
    可以发现,多了一种转移出来 dp[i][x+1]=dp[i-1][x],其它转移都是不会变的
    所以把dp[i-1][x]的值提前记录下来,然后在线段树更新完后再去用这个值更新dp[i][x+1] 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 500005
#define ll long long 

ll n,a[N],p[N],m,b[N];
const ll INF = 1e16;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll mi[N<<2],lazy[N<<2];
void pushdown(int rt){
    if(lazy[rt]!=0){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        mi[rt<<1]+=lazy[rt];
        mi[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
}
void update1(int L,int R,ll v,int l,int r,int rt){// 区间加 
    if(L>R)return;
    if(L<=l && R>=r){
        lazy[rt]+=v;mi[rt]+=v;
        return;
    }
    pushdown(rt);
    int m=l+r>>1;
    if(L<=m)update1(L,R,v,lson);
    if(R>m)update1(L,R,v,rson);
    mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}
void update2(int pos,ll v,int l,int r,int rt){// 单点取min 
    if(l==r){
        mi[rt]=min(mi[rt],v);return;
    }
    pushdown(rt);
    int m=l+r>>1;
    if(pos<=m)update2(pos,v,lson);
    else update2(pos,v,rson);
    mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}
ll query(int pos,int l,int r,int rt){// 单点查询 
    if(l==r)return mi[rt];
    pushdown(rt);
    int m=l+r>>1;
    if(pos<=m)return query(pos,lson);
    else return query(pos,rson);
}

int main(){
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)scanf("%lld",&p[i]);
    cin>>m;
    for(int i=1;i<=m;i++)scanf("%lld",&b[i]);
    
    update1(2,m+1,INF,1,m+1,1);//dp[0][1]=0
    for(int i=1;i<=n;i++){
        int x=lower_bound(b+1,b+1+m,a[i])-b;
        if(x==m+1){  // a[i]必须删 
            update1(1,m+1,p[i],1,m+1,1); 
        } else {
            ll tmp=INF;
            if(a[i]==b[x])tmp=query(x,1,m+1,1);
            if(p[i]<0)
                update1(1,m+1,p[i],1,m+1,1);
            else update1(1,x,p[i],1,m+1,1);
            if(a[i]==b[x] && tmp<INF)
                update2(x+1,tmp,1,m+1,1);
        } 
    }
    ll res=query(m+1,1,m+1,1);
    if(res<1e15){
        puts("YES");cout<<res;
    }else {
        puts("NO");
    }
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12769849.html