http://codeforces.com/problemset/problem/940/E

题意

将数组a划分成若干段,使每段的f值之和最小,其中f值是区间内元素和减去前k/c(下取整)小的数。

分析

这题去看了题解[跪下认错[???]]

首先是一个重要的结论
如果多段区间连在一起,显然拆开不会变差。一段区间内最小的k个值<=k段区间里最小的值。
不知道好不好理解,可以先通过两个区间拼在一起的情况来说明。
[a[1],a[2],a[3],…,a[k]],[a[k+1],a[k+2],…a[k+l]]
那么如果两段区间不合在一起,f=a[1,k]的最小值+a[k+1,k+l]的最小值
如果两段区间合在一起,那么f=a[1,k+l]的最小值+次小值。
显然前者的f大于等于后者的f

然后以此类推,对于任何多个区间拼合成的区间一定不比把这些区间分开优。
考虑dp[i] 表示前面i个元素已经分进区间之后f的最小值。那么显而易见的。
dp[i]=min(dp[i-1],dp[i-l]+min{a[i-l+1,i]})+a[i];

可以用线段树或者单调队列优化[然而速度非常明显的区分开了两个算法…]

code

#include<bits/stdc++.h>
#define ll long long
#define M 100005
using namespace std;
void read(int &x){x=0; char c=getchar();for (;c<48;c=getchar());for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
void read(ll &x){x=0; char c=getchar();for (;c<48;c=getchar());for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
struct Queue{ll a[M];int id[M],l,r;void add(int val,int Id){for (;r>=l&&a[r]>=val;r--);a[++r]=val; id[r]=Id;}void del(int Id){if (id[l]==Id)l++;}ll qu(){return a[l];}void pt(){for (int i=l;i<=r;i++)printf("%d %lld\n",id[i],a[i]);}
}Q;
inline void Max(ll &x,ll y){if (x<y)x=y;
}
ll dp[M],a[M],sum;
int main(){//freopen("1.in","r",stdin);int n,c;read(n); read(c);Q.l=1;for (int i=1;i<=n;i++)read(a[i]),sum+=a[i];for (int i=1;i<=n;i++){Q.add(a[i],i);dp[i]=dp[i-1];if (i-c+1>=1){Max(dp[i],dp[i-c]+Q.qu());Q.del(i-c+1);}}printf("%lld\n",sum-dp[n]);return 0;
}

Cashback [CodeForces - 940E]相关推荐

  1. Codeforces 940E - Cashback

    940E - Cashback 思路: dp+rmq 可以证明最后划分的区间可以由长度为1和长度为c的区间组成的,这样就可以用O(n)的dp求了,区间最小值随便拿什么维护都可以 状态:dp[i]表示到 ...

  2. [Codeforces 940E]Cashback(dp+set)

    题目链接:http://codeforces.com/problemset/problem/940/E 思路:划分任意长度,每c长度区间可去除一个最小值,所以划分方法就是单独自己一个或者长度为c的区间 ...

  3. Codeforces 940E Cashback

    Cashback 题意:一共给你N个数, 然后将他们分成连续的子集, 每个集合可以删除 元素个数/c  个最小元素, 然后求每个集合删除元素后的总和. 题解:我们将集合分为1个元素或者K个元素,每K个 ...

  4. codeforces 940E Cashback 有趣的dp

    题解 这么明显的一个dp,我怎么就没看出来呢?! 首先我们需要一些前提条件:任何划分出来的一个区间的长度不应该超过c. 如果这个区间长度大于c,那么设len=n∗c+klen=n∗c+klen=n*c ...

  5. [Codeforces 940E]Cashback

    Description 题库链接 给你两个整数 \(n,c\) ,以及一个数列 \(A\) ,让你将序列分为许多段.对于每一段,他的价值为序列内除了最小的 \(\left\lfloor\frac{le ...

  6. CodeForces - 940E Cashback (DP+思维模型)

    题意:给你长度为n的数列,一段序列的价值是,所有数的总和-最小的len/c的数的和,求如何分割数列,使得答案总和最小. 分析:一开始看到向下取整不外乎两种情况:一是用计算机处理,那么表明用暴力,emm ...

  7. codeforces 940E. Cashback(线性dp)

    传送门 题意:给出一个nnn个数的序列,要求将序列分成若干段,对于一段长度为kkk的自动删去最小的⌊kc⌋\left \lfloor \frac{k}{c} \right \rfloor⌊ck​⌋个数 ...

  8. Codeforces 940E: Cashback 单调队列优化DP

    传送门 题目描述 给你一个长度为n的数列a和整数c 你需要把它任意分段 每一段假设长度为k,就去掉前 ⌊kc⌋\lfloor\frac{k}{c}\rfloor⌊ck​⌋小的数 最小化剩下的数的和 分 ...

  9. CodeForces 940E

    题意略. 这个题目我开始题意理解得有点问题.本题的实质是在这个数列中选择一些数字,使得选出的这些数字之和最大,用dp来解. 我们先要明确:当我选择数列长度为2 * c时,不如把这个长度为2 * c的劈 ...

最新文章

  1. RoadFlow工作流引擎安装与部署
  2. PHPUnit单元测试 - 我看过的PHP开源框架
  3. 如何关闭eslint检测代码格式报错
  4. 技能高考本科计算机类,技能高考多少分上本科
  5. python 矩阵元素相加_Numpy中元素级运算
  6. VMware 下Linux无法上网 新增支持WIFI方式 无线连接
  7. Xception,Inception-ResNet,SENet(Squeeze-and-Excitation)
  8. Solidity编程 二 之Solidity安装
  9. 双系统如何在Centos7中添加GRUB2启动项
  10. Hive的概述、流程和优化
  11. 【易语言】大漠插件使用
  12. excel随机数_软网推荐:Windows环境下快速生成随机数
  13. 猫、路由器、交换机的区别
  14. 火狐插件 测试浏览器兼容性_在Firefox中测试和报告插件兼容性
  15. YoMail 隐藏小功能之怎样在yomail里使用石墨文档?
  16. 记一个异常原因,QQ和微信可以正常使用,无法访问百度
  17. php汉字占几个字节,php一个汉字几个字节
  18. matlab实现图割算法中的最大流最小割Max-flow/min-cut问题(一)
  19. Intel 酷睿 i3、i5、i7 CPU 处理器之间有什么区别
  20. HTML+CSS+JavaScript实现的动态爱心,超简单直接用!

热门文章

  1. 程序员脱发问题之个人经历
  2. 笔记:单轴上的动量守恒
  3. MySQL8功能详解——角色
  4. Java中为什么不能用“==”判断字符串是否相等
  5. 逻辑代数基本公式及定律
  6. HttpURLConnection源码分析
  7. 最全Java项目合集(附源码课件),可完美运行
  8. java生成短信验证码 字母加数字的验证码
  9. vue 自定义指令
  10. 二三层报头及IP分片详解