zoukankan      html  css  js  c++  java
  • CF940E Cashback(DP)

    题意:

    给定一个数C,对一个序列作切割,每一段对答案的贡献是这一段的元素之和减去这一段里最小的Len/C个数之和,Len指这一段的长度。

    询问最小答案。

    题解:

    有一个结论是,两个长度为C的序列对答案的贡献一定小于这两个序列合并起来对答案的贡献。

    有个贪心的做法就是只切长度为1和长度为C的序列。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+100;
    ll dp[maxn];
    ll c[maxn];
    ll a[maxn];
    ll n,m;
    struct node {
        ll l,r,sum;
    }segTree[maxn<<2];
    void build (ll i,ll l,ll r) {
        segTree[i].l=l;
        segTree[i].r=r;
        if (l==r) {
            segTree[i].sum=a[l];
            return;
        }
        ll mid=(l+r)>>1;
        build(i<<1,l,mid);
        build(i<<1|1,mid+1,r);
        segTree[i].sum=min(segTree[i<<1].sum,segTree[i<<1|1].sum);
    }
    ll query (int i,int l,int r) {
        if (segTree[i].l>=l&&segTree[i].r<=r) 
            return segTree[i].sum;
        ll mid=(segTree[i].l+segTree[i].r)>>1;
        ll ans=1e9;
        if (l<=mid)
            ans=min(ans,query(i<<1,l,r));
        if (r>mid)
            ans=min(ans,query(i<<1|1,l,r));
        return ans;
    }
    int main () {
        cin>>n>>m;
        for (int i=1;i<=n;i++) dp[i]=1e18;
        for (int i=1;i<=n;i++) cin>>a[i];
        for (int i=1;i<=n;i++) c[i]=c[i-1]+a[i];
        build(1,1,n);
        for (int i=1;i<=n;i++) {
            dp[i]=min(dp[i],dp[i-1]+a[i]);
            if (i>=m)
                dp[i]=min(dp[i],dp[i-m]+c[i]-c[i-m]-query(1,i-m+1,i));
        }
        cout<<dp[n];
    }
  • 相关阅读:
    java环境配置为1.7jdk为什么cmd java -version查看版本是1.8
    bulid path 引 jar包 步骤
    eclipse 报错
    PLSQL使用技巧
    Oracle sqlplus不是内部或外部命令
    SVN 插件安装到Myeclipse10 上(经典)
    socket学习
    Eclipse 配置 插件svn 包步骤
    如何在Eclipse中使用SVN(经典)
    linux 下搭建LAMP
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13641883.html
Copyright © 2011-2022 走看看