题目描述

$visit\text{_}world$发现有下优化问题可以用很平凡的技巧解决,所以他给你分享了这样一道题:
现在有长度为$N$的整数序列$\{ a_i\}$,你需要从中选出$K$个不想叫的连续子区间(可以存在元素不被选),从左到右记它们的和为$s_1,s_2,...,s_k$,我们的优化目标是最大化下述和式:
$$\sum \limits_{i=1}^{k-1}|s_i-s_{i+1}|$$
你只需要输出这个最大的和即可。


输入格式

第一行两个整数$N,K$,意义如上。
接下来一行$N$个整数,第$i$个数表示$a_i$,保证有$|a_i|\leqslant 10^4$。


输出格式

输出一行一个整数,表示答案。


样例

样例输入:

5 3
5 2 4 3 1

样例输出:

12


数据范围与提示

样例解释:

选择$(5),(2,4,3),(1)$三个子段,$|5-9|+|9-1|=12$

数据范围:

对于全部的测试数据,保证$N\leqslant 3\times 10^4,K\leqslant \min(N,200)$。
$\bullet$子任务$1$($10$分):$K\leqslant 3$。
$\bullet$子任务$2$($30$分):$N\leqslant 400,K\leqslant 50$。
$\bullet$子任务$3$($20$分):$N\leqslant 10^3,K\leqslant 100$。
$\bullet$子任务$4$($40$分):无特殊限制。


题解

利用贪心思想,这$k$个序列一定是一高一低的,不可能连续三个及以上持续上升或下降。

对于高的序列,其贡献为$+2$;对于低的序列,其贡献为$-2$;而中间也会有一些并不选的状态,其贡献为$0$,而对于这些状态,其接下来会有高或低的序列,为了区分它们,不妨将其称为上升状态$or$下降状态。

考虑$DP$,设$dp[i][j][0/1/2/3]$表示前$i$个数,分成了$j$段,当前状态是高、低、上升、下降状态。

状态转移很简单,需要注意的是对于边界的处理,即$j=1$和$j=K$的情况。

时间复杂度:$\Theta(NK)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int N,K;
int w[30001];
int dp[30001][201][4];
int main()
{
scanf("%d%d",&N,&K);
for(int i=1;i<=N;i++)
scanf("%d",&w[i]);
memset(dp,-0x3f,sizeof(dp));
for(int i=1;i<=N;i++)dp[i][0][0]=dp[i][0][1]=dp[i][0][2]=dp[i][0][3]=0;
dp[0][0][0]=dp[0][0][1]=dp[0][0][2]=dp[0][0][3]=0;
for(int i=1;i<=N;i++)
{
dp[i][1][0]=max(dp[i-1][1][0],dp[i-1][0][2])+w[i];
dp[i][1][1]=max(dp[i-1][1][1],dp[i-1][0][3])-w[i];
dp[i][1][2]=max(dp[i-1][1][2],dp[i][1][1]);
dp[i][1][3]=max(dp[i-1][1][3],dp[i][1][0]);
dp[i][K][0]=max(dp[i-1][K][0],dp[i-1][K-1][2])+w[i];
dp[i][K][1]=max(dp[i-1][K][1],dp[i-1][K-1][3])-w[i];
dp[i][K][2]=max(dp[i-1][K][2],dp[i][K][1]);
dp[i][K][3]=max(dp[i-1][K][3],dp[i][K][0]);
for(int j=2;j<K;j++)
{
dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j-1][2])+2*w[i];
dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j-1][3])-2*w[i];
dp[i][j][2]=max(dp[i-1][j][2],max(dp[i][j][1],dp[i-1][j-1][2]));
dp[i][j][3]=max(dp[i-1][j][3],max(dp[i][j][0],dp[i-1][j-1][3]));
}
}
printf("%d",max(dp[N][K][2],dp[N][K][3]));
return 0;
}

rp++

[CSP-S模拟测试]:优化(贪心+DP)的更多相关文章

  1. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  2. [CSP-S模拟测试]:y(DP+bitset)

    题目背景 $\frac{1}{4}$遇到了一道水题,叕完全不会做,于是去请教小$D$.小$D$懒得理$\frac{1}{4}$,直接就离开了.于是,$\frac{1}{4}$只好来问你,这道题是这样的 ...

  3. [CSP-S模拟测试]:施工(DP+单调栈+前缀和)

    题目描述 小$Y$家门前有一条街道,街道上顺序排列着$n$幢建筑,其中左起第$i$幢建筑的高度为$h_i$.小$Y$定义街道的不美观度为所有相邻建筑高度差的绝对值之和乘上常数$c$,为了改善街道环境, ...

  4. [CSP-S模拟测试]:biology(DP)

    题目传送门(内部题23) 输入格式 第一行有$2$个整数$n,m$.接下来有$n$行,每行$m$个整数,表示$a$数组.接下来有$n$行,每行$m$个整数,表示$b$数组. 输出格式 一行一个整数表示 ...

  5. [CSP-S模拟测试]:F(DP+线段树)

    题目传送门(内部题49) 输入格式 第一行四个整数$n,q,a,b$.接下来$n$行每行一个整数$p_i$. 输出格式 一行一个整数表示答案. 样例 样例输入: 10 3 3 7 样例输出: 数据范围 ...

  6. 5.12 省选模拟赛 T2 贪心 dp 搜索 差分

    LINK:T2 这题感觉很套路 但是不会写. 区间操作 显然直接使用dp不太行 直接爆搜也不太行复杂度太高. 容易想到差分 由于使得整个序列都为0 那么第一个数也要i差分前一个数 强行加一个0 然后 ...

  7. [CSP-S模拟测试]:蛇(DP+构造+哈希)

    题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...

  8. [CSP-S模拟测试]:最小值(DP+乱搞)

    题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...

  9. [CSP-S模拟测试]:花(DP)

    题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 ...

随机推荐

  1. CodeForces-431D Random Task

    题目描述 求一个\(n\),使得\(n+1\)到\(2n\)这些数的二进制中恰好有\(k\)个\(1\)的数有\(m\)个. Input 输入包含两个正整数\(m,k\).$(0<=m<= ...

  2. Gym 101466(完整)

    题目链接 :点击此处 ## Problem A 题意: 给你n个数,重定义两个数之间的加法不进位,求这些数中两个数相加的最大值和最小值. 题解: 字典树.我们首先将前i-1为放入字典树中,然后在查询第 ...

  3. Hdu 4738【tanjan求无向图的桥】割边判定定理 dfn[x] < low[y]

    题目: 曹操在长江上建立了一些点,点之间有一些边连着.如果这些点构成的无向图变成了连通图,那么曹操就无敌了.刘备为了防止曹操变得无敌,就打算去摧毁连接曹操的点的桥.但是诸葛亮把所有炸弹都带走了,只留下 ...

  4. 0-1-Tree CodeForces - 1156D (并查集)

    大意: 给定树, 边权为黑或白, 求所有有向路径条数, 满足每走过一条黑边后不会走白边. 这题比赛的时候想了个假算法, 还没发现..... 显然所求的路径要么全黑, 要么全白, 要么先全白后全黑, 所 ...

  5. google浏览器切换成中文

    新浪下载地址:http://down.tech.sina.com.cn/content/40975.html 默认字体好像是西班牙语 1.浏览器地址chrome://settings/language ...

  6. AWS EC2 搭建 Hadoop 和 Spark 集群

    前言 本篇演示如何使用 AWS EC2 云服务搭建集群.当然在只有一台计算机的情况下搭建完全分布式集群,还有另外几种方法:一种是本地搭建多台虚拟机,好处是免费易操控,坏处是虚拟机对宿主机配置要求较高, ...

  7. vue中如何开发插件

    1.vue中提供了install方法用来开发插件 官方:Vue.js 的插件应该有一个公开方法 install.这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象. 2.我的插件目 ...

  8. python多线程之threading、ThreadPoolExecutor.map

    背景: 某个应用场景需要从数据库中取出几十万的数据时,需要对每个数据进行相应的操作.逐个数据处理过慢,于是考虑对数据进行分段线程处理: 方法一:使用threading模块 代码: # -*- codi ...

  9. Django新建第一个投票应用

    1:在Pycharm的命令端口,确保执行文件路径是与mysite同级 $ python3 manage.py startapp polls 系统会自动生成polls应用的目录,其结构如下 polls/ ...

  10. mongoose 开源http库(2) --HTTP服务示例

    要创建HTTP服务器,请按照以下格式: 通过调用mg_bind()或mg_bind_opt()创建侦听连接 调用mg_set_protocol_http_websocket()创建listening连 ...