zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    LeetCode——Generate Parentheses
    LeetCode——Best Time to Buy and Sell Stock IV
    LeetCode——Best Time to Buy and Sell Stock III
    LeetCode——Best Time to Buy and Sell Stock
    LeetCode——Find Minimum in Rotated Sorted Array
    Mahout实现基于用户的协同过滤算法
    使用Java对文件进行解压缩
    LeetCode——Convert Sorted Array to Binary Search Tree
    LeetCode——Missing Number
    LeetCode——Integer to Roman
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/13339617.html
Copyright © 2011-2022 走看看