【Foreign】动态规划 [分治][DP]
动态规划
Time Limit: 50 Sec Memory Limit: 128 MB
Description
我们想把这n个数切成恰好k段区间。之后这n个数的价值为这k段区间的价值和。
我们想让最终这n个数的价值和尽可能少。
例如6个数1,1,2,2,3,3要切成3段,一个好方法是切成[1],[1,2],[2,3,3],这样只有第三个区间有1的价值。因此这6个数的价值为1。
Input
接下来一行n个数ai表示这n个数。
Output
一个数表示答案。
Sample Input
1 2 1 2 1 2 1 2 1 2
Sample Output
HINT
Solution
首先,暴力DP非常显然,f[i][j] 表示分了 i 段,当前做到第 j 个元素的最小值。
那么 f[i][j] = f[i - 1][k] + sum(k + 1, i)。我们打一个表,发现决策具有单调性。
但是显然,对于这道题,我们不能直接二分转移来的位置,由于sum并不好求。
所以我们可以考虑运用分治。执行k次。Solve(l, r, L, R)表示 j∈[l, r],from∈[L, R]。
那么我们对于[l, r],考虑mid从[L, R]中的哪一个转移过来,假设是MidFrom。
那么由于决策单调性,所以[l, mid - 1]的决策点一定在[L, MidFrom],[mid + 1, r]的决策点一定在[MidFrom, R]。
移动两个指针now_l, now_r,维护sum即可。(复杂度我也不会证明呀QWQ)
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9 + ;
const s64 INF = 1e18; int get()
{
int res = , Q = ; char c;
while( (c = getchar()) < || c > )
if(c == '-') Q = -;
if(Q) res = c - ;
while( (c = getchar()) >= && c <= )
res = res * + c - ;
return res * Q;
} int n, k;
int a[ONE], cnt[ONE]; s64 record[ONE], f[ONE], value;
int now_l, now_r; void Move(int l, int r)
{
while(now_r < r) cnt[a[++now_r]]++, value += cnt[a[now_r]];
while(l < now_l) cnt[a[--now_l]]++, value += cnt[a[now_l]];
while(now_r > r) value -= cnt[a[now_r]], cnt[a[now_r--]]--;
while(l > now_l) value -= cnt[a[now_l]], cnt[a[now_l++]]--;
} void Solve(int l, int r, int L, int R) //j=l~r, from = L~R
{
if(l > r) return;
int mid = l + r >> , MidFrom;
s64 Ans = INF;
for(int from = L; from <= R; from++)
{
if(from >= mid) break;
Move(from + , mid);
if(f[from] + value < Ans)
Ans = f[from] + value, MidFrom = from;
}
record[mid] = Ans;
Solve(l, mid - , L, MidFrom);
Solve(mid + , r, MidFrom, R);
} int main()
{
n = get(); k = get();
for(int i = ; i <= n; i++)
a[i] = get(); for(int i = ; i <= n; i++) f[i] = INF;
f[] = ;
for(int j = ; j <= k; j++)
{
for(int i = ; i <= n; i++) cnt[i] = -;
now_l = now_r = ; value = , cnt[a[]] = ;
Solve(, n, , n - );
for(int i = ; i <= n; i++)
f[i] = record[i], record[i] = ;
}
printf("%lld", f[n]);
}
【Foreign】动态规划 [分治][DP]的更多相关文章
- 【学习笔记】动态规划—各种 DP 优化
[学习笔记]动态规划-各种 DP 优化 [大前言] 个人认为贪心,\(dp\) 是最难的,每次遇到题完全不知道该怎么办,看了题解后又瞬间恍然大悟(TAT).这篇文章也是花了我差不多一个月时间才全部完成 ...
- BZOJ 4518 [Sdoi2016]征途(分治DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4518 [题目大意] 给出一个数列,分成m段,求方差最小,答案乘上m的平方. [题解] ...
- HDU 3507 Print Article(CDQ分治+分治DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3507 [题目大意] 将长度为n的数列分段,最小化每段和的平方和. [题解] 根据题目很容易得到dp ...
- 洛谷P2634 聪聪可可 [国家集训队] 点分治/dp
正解:点分治/dp 解题报告: 传送门! 这题有两个做法,都是我不擅长的就都说下好了QAQ 首先这题一看到就会想到点分治? 也确实可以用点分治,那就直接用点分治鸭 每次求出到当前根距离余数为0,1,2 ...
- [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...
- 初探动态规划(DP)
学习qzz的命名,来写一篇关于动态规划(dp)的入门博客. 动态规划应该算是一个入门oier的坑,动态规划的抽象即神奇之处,让很多萌新 萌比. 写这篇博客的目标,就是想要用一些容易理解的方式,讲解入门 ...
- Leetcode之动态规划(DP)专题-详解983. 最低票价(Minimum Cost For Tickets)
Leetcode之动态规划(DP)专题-983. 最低票价(Minimum Cost For Tickets) 在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行.在接下来的一年里,你要旅行的 ...
- Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings)
Leetcode之动态规划(DP)专题-647. 回文子串(Palindromic Substrings) 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同开始位置或结束位置的子 ...
- Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes)
Leetcode之动态规划(DP)专题-474. 一和零(Ones and Zeroes) 在计算机界中,我们总是追求用有限的资源获取最大的收益. 现在,假设你分别支配着 m 个 0 和 n 个 1. ...
随机推荐
- Struts1简单开发流程梳理
共享数据的4种范围MVC设计模式JSP model1.JSP model2struts实现MVC机制(ActionServlet.Action)struts-config.xml ActionServ ...
- 『编程题全队』Alpha 阶段冲刺博客集合
『编程题全队』Alpha 阶段冲刺博客集合 »Day1 2018年4月19日 博客连接:『编程题全队』Alpha 阶段冲刺博客Day1 »Day2 2018年4月20日 博客连接:『编程题全队』Alp ...
- 2018最新Web前端经典面试试题及答案
javascript: JavaScript中如何检测一个变量是一个String类型?请写出函数实现 typeof(obj) === "string" typeof obj === ...
- mysql按日期分组统计数据
最近在做一个招聘网时,需要显示一个月内企业招聘信息的发布数量,按日期分组统计,刚开始是直接从源数据库表里面进行group by,但这样子就出现日期不连续的问题了,我想要的效果是,若当天没有数据,则显示 ...
- JS 随机整数
<script> function GetRandomNum(Min,Max){ var Range = Max - Min; var Rand = Math.random() ...
- 第214天:Angular 基础概念
一.Angular 简介 1. 什么是 AngularJS - 一款非常优秀的前端高级 JS 框架 - 最早由 Misko Hevery 等人创建 - 2009 年被 Google 公式收购,用于其多 ...
- 【转】VS2012简单的使用感受+插件推荐
转自:http://blog.sina.com.cn/s/blog_58c506600101b34t.html ~PS:后面有博主自己补充的VS2013的哦~ 1.Visual Studio Achi ...
- 【BZOJ2006】【NOI2010】超级钢琴(主席树,优先队列)
[BZOJ2006]超级钢琴(主席树,优先队列) 题面 BZOJ 题解 既然是一段区间 首先就要变成单点 所以求一个前缀和 这个时候贪心很明显了: 枚举每一个点和可以和它组成一段的可行的点 全部丢进一 ...
- BZOJ2276 [Poi2011]Temperature 【单调队列】
题目链接 BZOJ2276 题解 一开始看错题,以为求的是可以不连续的,想出一个奇怪的线段树,发现空间根本开不下?? 题目要我们求连续的最长可能不下降区间 对于区间\([l,r]\)如果合法,当且仅当 ...
- 解题:CF949D Curfew
题面 整体的思路就是在均摊每个宿舍的人数,注意一个人可以跑好几次=.= 可以发现多的学生往中间跑一定能跑过宿管,所以只考虑学生们能不能及时跑到人不够的宿舍.对两边记录两个已经满足要求的宿舍,然后用前/ ...