题意

给定$n$个数,将其划分成若干个连续的子序列,求最小价值,数组价值定义为,数组和减去$\lfloor \frac{k}{c} \rfloor$,$k$为数组长度,$c$为给定数


可以列得朴素方程$f_i=\min_{j \le i} {f_j+w(j+1,i)}$,复杂度$O(n^2)$

考虑划分的区间长度$k$,若$k=c$,那么只需要去掉区间的最小值,若$k$是$c$的整数倍,那么需要去掉$k/c$个最小值,那么把$k$分成$k/c$个长度为$c$的段,删除的最小值为每个段的最小值之和一定不小于长度为$k$的段的$k/c$个最小值的和,所以最优的分段一定是分成若干个长度为$c$的段

在考虑$k$不被整除的情况,若$k=c+p,p < k$,那么这一段也只会删掉一个最小值,随着$p$的增大,最小值单调不增,所以不会更优。若$k<c$,那么将不会删除值,也就是代价不会转移,可以将其看成分成$k$个$1$

所以可以将方程化简为$f_i=\min {f_{i-1},f_{i-c}+u(j+1,i) }$ ,$u(i,j)$为$[i,j]$的区间和减去区间最小值,可以利用st表预处理得到

时间复杂度$O(n\log n)$

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, c, a[100005], st[100005][35];
LL dp[100005], sum;
int min_(int l, int r) {
int x = (int)(log(double(r - l + 1)) / log(2.0));
return min(st[l][x], st[r - (1 << x) + 1][x]);
}
int main() {
scanf("%d%d", &n, &c);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]); st[i][0] = a[i]; sum += a[i];
}
for(int j = 1; (1 << j) <= n; ++j) {
for(int i = 1; i + (1 << j - 1) <= n; ++i) {
st[i][j] = min(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
}
}
for(int i = c; i <= n; ++i) {
dp[i] = max(dp[i - 1], dp[i - c] + min_(i - c + 1, i));
}
cout << sum - dp[n] << endl;
return 0;
}

【Codeforces Round #466】E. Cashback DP+ST表的更多相关文章

  1. Codeforces Round #466 (Div. 2) E. Cashback

    Codeforces Round #466 (Div. 2) E. Cashback(dp + 贪心) 题意: 给一个长度为\(n\)的序列\(a_i\),给出一个整数\(c\) 定义序列中一段长度为 ...

  2. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  3. Codeforces Round #278 (Div. 1) B - Strip dp+st表+单调队列

    B - Strip 思路:简单dp,用st表+单调队列维护一下. #include<bits/stdc++.h> #define LL long long #define fi first ...

  4. Codeforces Round #466 (Div. 2)

    所有的题目都可以在CodeForces上查看 中间看起来有很多场比赛我没有写了 其实是因为有题目没改完 因为我不想改,所以就没有写了(大部分题目还是改完了的) 我还是觉得如果是打了的比赛就一场一场写比 ...

  5. Codeforces Round #466 (Div. 2) Solution

    从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...

  6. Codeforces Round #466

    A. Points on the line 题意 给定一条直线上\(n\)个点,要求去掉最少的点,使得直线上相距最远的两个点的距离\(\leq d\). 思路 枚举长度为\(d\)的区间. Code ...

  7. 刷题总结——Bob's Race(hdu4123 树形dp+st表)

    题目: Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the ro ...

  8. (DP ST表 线段树)51NOD 1174 区间中最大的数

    给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,最大的数是多少.   例如: 1 7 6 3 1.i = 1, j = 3,对应的数为7 6 3,最大的数为7. ...

  9. Codeforces 359D Pair of Numbers | 二分+ST表+gcd

    题面: 给一个序列,求最长的合法区间,合法被定义为这个序列的gcd=区间最小值 输出最长合法区间个数,r-l长度 接下来输出每个合法区间的左端点 题解: 由于区间gcd满足单调性,所以我们可以二分区间 ...

随机推荐

  1. js读取json包装的map集合

    后台 Map<String,Integer> map = new HashMap<>(); map.put("你好1", 1); map.put(" ...

  2. #define的使用方法体会

    #define 创建一个宏,该宏是标识符或參数化标识符与标记字符串的关联. 在定义宏之后.编译器可用标记字符串替换源文件里标识符的每一个匹配项. 双击以所有折叠.">语法 #defin ...

  3. 44.Android MD5Util

    44.Android MD5Util public class MD5Util { public static String getMD5String(String key) { char hexDi ...

  4. C语言基础知识【程序结构】

    C 程序结构1.C 程序主要包括以下部分:预处理器指令函数变量语句 & 表达式注释2.#include <stdio.h> int main(){   /* 我的第一个 C 程序 ...

  5. Java线程面试题:设计四个线程,其中两个线程每次对 j 加 1,另外两个每次对 j 减 1,程序如下。

    package thread; /** * Java线程面试题 * @author zhongfg * @date 2015-06-16 */ public class ThreadInterview ...

  6. City Game(最大子矩阵)

    Bob is a strategy game programming specialist. In his new city building game the gaming environment ...

  7. iOS 添加震动效果

    开发过程中,有时候会碰到点击按钮或者某个动画会配合震动效果:下面介绍iOS开发过程中的震动添加: 导入:#import <AudioToolbox/AudioToolbox.h> 在需要出 ...

  8. Python 面试题(上)

    Python语言特性 1 Python的函数参数传递 看两个例子: a = 1 deffun(a): a = 2 fun(a) printa # 1 a = [] deffun(a): a.appen ...

  9. R语言数据管理(三):数据读入

    R的数据读入非常灵活,即可以在R软件中直接输入,也可以读入外部数据. 一.直接输入数据 ①c()函数 ②scan()函数 其功能类似c()函数,scan()实际上是一种键盘输入数据函数.当输入scan ...

  10. python 统计单词出现次数

    #use python3.6 import re from collections import Counter FILESOURCE = './abc.txt' def getMostCommonW ...