题意:

  给定一个序列,你要将其分为k段,总的代价为每段的权值之和,求最小代价。

  定义一段序列的权值为$\sum_{i = 1}^{n}{\binom{cnt_{i}}{2}}$,其中$cnt_{i}$表示当前这段序列中数字大小为i的数的个数。

题解:

  先考虑暴力DP, f[i][j]表示DP到i位,分为j段的最小代价。

  则$f[i][j] = min(f[l - 1][j] + sum[l][i])$,其中sum[l][i]表示区间[l, i]分成一段的代价。

  然后可以发现,这是具有决策单调性的,简易证明:

    首先设l < j < i.

    假设f[i][t]从f[j - 1][t - 1]转移而来,则有$f[j - 1][t - 1] + w[j][i] < f[l - 1][t - 1] + w[l][i]$.

    现在考虑i + 1的情况,观察到$\binom{cnt_{i}}{2}$的式子经过化简后恰好可以表示0 ~ n - 1这个等差数列的求和公式,因此w[j][i]可以O(1)的转移到w[j][i + 1],即w[j][i + 1] = w[j][i] + sum[j][i];.sum[j][i]表示这个区间内某个颜色的数量(懒得再打一维了,这个理解一下就好,只是这么表示而已)

    所以f[i + 1][t] = min(f[j - 1][t - 1] + w[j][i] + sum[j][i], f[l - 1][t - 1] + w[l][i] + sum[l][i]);//可以发现,由于$l < j$,所以$sum[l][i] >= sum[j][i]$,而式子的另一部分,也就是和f[i][t]相同的部分也是左边小于右边,因此j一定比l优。

   因此可以利用决策单调性来优化DP,因为无法O(1)得知w[i][j]的值,因此无法用二分单调栈来进行优化,于是我们考虑分治。

   不知道如何用分治优化决策单调性戳:决策单调性优化DP

  然后注意到对于这题而言,暴力转移的复杂度还是太高了,于是考虑利用以下之前已有的信息,设当前已经被求出权值的区间为[ll, rr],权值为rnt.

  那么每次转移的时候暴力将这个区间转移至当前需要的区间,于是就可以做到重复利用之前已经求出的信息。   

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 101000
#define LL long long
#define inf 1e18 int n, k, now, ll, rr;
int s[AC], sum[AC];
LL f[AC][], rnt; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} void pre()
{
n = read(), k = read();
for(R i = ; i <= n; i ++) s[i] = read();
} void cal(int l, int r)
{
while(rr < r) rnt += sum[s[++ rr]] ++;
while(rr > r) rnt -= -- sum[s[rr --]];
while(ll > l) rnt += sum[s[-- ll]] ++;
while(ll < l) rnt -= -- sum[s[ll ++]];
} void solve(int l, int r, int kl, int kr)//当前区间[l, r],决策点区间[kl, kr]
{
if(l > r) return ;
int mid = (l + r) >> , k = -, b = min(mid, kr);
for(R i = kl; i <= b; i ++)//枚举当前段开头
{
cal(i, mid);
if(rnt + f[i - ][now - ] < f[mid][now])
f[mid][now] = rnt + f[i - ][now - ], k = i;
}
solve(l, mid - , kl, k), solve(mid + , r, k, kr);
} void work()
{
for(R i = ; i <= n; i ++)
for(R j = ; j <= k; j ++) f[i][j] = inf;
ll = , rr = n;
for(R i = ; i <= n; i ++) rnt += sum[s[i]] ++;
for(now = ; now <= k; now ++) solve(, n, , n);//分层做k次
printf("%lld\n", f[n][k]);
} int main()
{
freopen("in.in", "r", stdin);
pre();
work();
fclose(stdin);
return ;
}

CF868F Yet Another Minimization Problem 分治决策单调性优化DP的更多相关文章

  1. Codeforces 868F. Yet Another Minimization Problem【决策单调性优化DP】【分治】【莫队】

    LINK 题目大意 给你一个序列分成k段 每一段的代价是满足\((a_i=a_j)\)的无序数对\((i,j)\)的个数 求最小的代价 思路 首先有一个暴力dp的思路是\(dp_{i,k}=min(d ...

  2. CF868F Yet Another Minimization Problem(决策单调性)

    题目描述:给定一个序列,要把它分成k个子序列.每个子序列的费用是其中相同元素的对数.求所有子序列的费用之和的最小值. 输入格式:第一行输入n(序列长度)和k(需分子序列段数).下一行有n个数,序列的每 ...

  3. 决策单调性优化dp 专题练习

    决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...

  4. Lightning Conductor 洛谷P3515 决策单调性优化DP

    遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...

  5. 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)

    传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...

  6. [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)

    第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...

  7. BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】

    Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt( ...

  8. 算法学习——决策单调性优化DP

    update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...

  9. BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】

    Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...

随机推荐

  1. AtCoder Beginner Contest 116 D - Various Sushi (贪心+栈)

    D - Various Sushi Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement ...

  2. 分享一个小设置-项目启动时服务器指向本地IIS

    背景,在X公司做的一个网站登录时需要域名的支持,就是说浏览器地址栏在localhost+端口号的形式下无法实现登录(必须是xxxx域名的形式), 但是很多时候都会先在线下进行测试,既然本地没有线上的环 ...

  3. linux中根据名称kill进程

    shell函数如下: # kill processes by name kbn() { line=`ps -a | grep $1` arr=($line) for((i=0;i<${#arr[ ...

  4. js总结:增加和减少文本框

    <head><script>var count = 0; function add(){ if(count<3) { count++; var x= document.c ...

  5. jmeter分布式压测(多台电脑一起压测)

    (1)在Windows下运行 操作步骤: 1)     有多台电脑,每台电脑上都有jmeter,而且这几台电脑都互相能ping通. 2)     在我的电脑的jmeter的配置文件bin目录下的jme ...

  6. PHP之位运算符

    使用场景: 1) 判断奇数偶数 ; $i < ; $i++) { ){ echo $i.PHP_EOL; } } //输出所有奇数 2)快速修改状态 $status1 = ; $status2 ...

  7. 自己用习惯的idea快捷键笔记

    Ctrl + Space 自动完成(win10下冲突不能用,自己换成 Alt + \ ) 切换方法是菜单中依次打开 file -> settings -> keymap,搜索complet ...

  8. js发布订阅模式实现

    //可以用于无相关页面或组件的事件.数据传递,减少在onShow中的业务,降低代码耦合 let events = {} /**订阅**/ function on(name, self, callbac ...

  9. MySQL客户端工具及SQL

    一.客户端命令介绍 mysql  mysqladmin mysqldump mysql 1.用于数据库的连接管理 2. mysqladmin 1. 2. mysqldump 1. 2.

  10. 安装 Tesserocr (填坑)

    参考: https://www.imooc.com/article/45278?block_id=tuijian_wz