zoukankan      html  css  js  c++  java
  • 【好题】线段树优化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");
        }
    }
  • 相关阅读:
    Java学习开篇
    《我的姐姐》
    世上本无事,庸人自扰之
    这48小时
    补觉
    淡定
    es java api 设置index mapping 报错 mapping source must be pairs of fieldnames and properties definition.
    java mongodb groupby分组查询
    linux 常用命令
    mongodb too many users are authenticated
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12769849.html
Copyright © 2011-2022 走看看