• CF940E Cashback


    这一段一直在CF上刷DP专项,虽然在考试的时候正解经常还想不出来,但是现在对于一道题仔细想一想n^2,n^3的暴力最起码会写了...... 

    分析:刚看到这道题时其实感觉挺玄乎的,自己在纸上写写画画一直也没有什么头绪,后来自己看数据范围强行手弄了一个n^3的暴力,就是定义dp[i]表示序列前i的最优答案,我们就可以枚举断点来进行区间拼接于是有dp[i]=min(dp[i],dp[j]+sum),由于需要O(n)计算前k小,成功的倒在了第七个点的2000的数据下......

    对于这道题我们可以想象一下,如果我们有一个长度不足以去除该区间内数字的小数列,那么其实它和将它分为一个一个单独的数字之后的效果是等效的,后者貌似还更好处理,那我们当然要用好处理的来计算,另外,如果我们选择了一个大区间,里面我们可以去除很多的数字,其实我们可以理解为就是每c的长度可以去除里面的一个最小的数字,之后再将相邻的长度为c的序列进行拼接,我们相当于就是向不同长度为c的序列之间填了一些数字,由于数字的大小这些数字对最终答案并没有什么影响,将他们和长度为c的序列分开,让它们单独成为一个序列似乎也可以,而且更好处理,和前面的处理方案相同。这样我们就可以把最终的答案序列理解为若干长度为c的序列和一些单独的点的集合,由于每个区间我们只除去一个数字即可,即最小值,我们就避免了求区间前k小的数字的麻烦,直接用一个线段树维护就可以了(在上午的时候思考如何求前k小卡了我好一阵QAQ),之后我们就可以尝试将区间划分一下,处理出每个区间的最小值,尝试让这些数字的总和最大,我们就可以得到最小的答案了。

     1 #include<bits/stdc++.h>
     2 #define int long long
     3 #define lson (t<<1)
     4 #define rson (t<<1|1)
     5 #define mid ((l+r)>>1)
     6 using namespace std;
     7 const int N=1e5+10;
     8 int dp[N],a[N];
     9 int b[N];
    10 int tree[N];
    11 void build(int t,int l,int r){
    12     if(l==r){
    13         tree[t]=a[l];
    14         return;
    15     }
    16     build(lson,l,mid); build(rson,mid+1,r);
    17     tree[t]=min(tree[lson],tree[rson]);
    18 }
    19 int query(int t,int l,int r,int ql,int qr){
    20     if(ql<=l && r<=qr){
    21         return tree[t];
    22     }
    23     if(qr<=mid) return query(lson,l,mid,ql,qr);
    24     else if(ql > mid) return query(rson,mid+1,r,ql,qr);
    25     else return min(query(lson,l,mid,ql,qr),query(rson,mid+1,r,ql,qr));
    26 }
    27 int cnt[N],tot;
    28 signed main(){
    29     int n,c;
    30     scanf("%lld%lld",&n,&c);
    31     dp[0]=0;
    32     for(int i=1;i<=n;++i) scanf("%lld",&a[i]),tot+=a[i];
    33     build(1,1,n);
    34     int ans=0;
    35     for(int i=1;i<=n-c+1;++i)
    36         cnt[i+c-1]=query(1,1,n,i,i+c-1);
    37     for(int i=c;i<=n;++i)
    38         dp[i]=dp[i-c]+cnt[i];
    39     for(int i=1;i<=n;++i){
    40         dp[i]=max(dp[i],dp[i-1]);
    41         if(i>=c) dp[i]=max(dp[i],dp[i-c]+cnt[i]);
    42     }
    43     printf("%lld
    ",tot-dp[n]);
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    vue-cli3.X快速创建项目
    Oracle中exists替代in语句
    Java根据子节点递归父节点
    记一次拆分包裹的算法
    Ajax下载文件
    Spring Boot 调用 MongoRepository时报org.springframework.beans.factory.NoSuchBeanDefinitionException错误的解决办法
    ORACLE拼日期
    记一次wordpress安装过程中遇到的问题及解决办法
    bootstrap动态添加Tab标签页
    Intellij Idea 2016 配置Tomcat虚拟目录
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/13339617.html
Copyright © 2020-2023  润新知