CF868F Yet Another Minimization Problem 分治决策单调性优化DP
题意:
给定一个序列,你要将其分为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的更多相关文章
- Codeforces 868F. Yet Another Minimization Problem【决策单调性优化DP】【分治】【莫队】
LINK 题目大意 给你一个序列分成k段 每一段的代价是满足\((a_i=a_j)\)的无序数对\((i,j)\)的个数 求最小的代价 思路 首先有一个暴力dp的思路是\(dp_{i,k}=min(d ...
- CF868F Yet Another Minimization Problem(决策单调性)
题目描述:给定一个序列,要把它分成k个子序列.每个子序列的费用是其中相同元素的对数.求所有子序列的费用之和的最小值. 输入格式:第一行输入n(序列长度)和k(需分子序列段数).下一行有n个数,序列的每 ...
- 决策单调性优化dp 专题练习
决策单调性优化dp 专题练习 优化方法总结 一.斜率优化 对于形如 \(dp[i]=dp[j]+(i-j)*(i-j)\)类型的转移方程,维护一个上凸包或者下凸包,找到切点快速求解 技法: 1.单调队 ...
- Lightning Conductor 洛谷P3515 决策单调性优化DP
遇见的第一道决策单调性优化DP,虽然看了题解,但是新技能√,很开森. 先%FlashHu大佬,反正我是看了他的题解和精美的配图才明白的,%%%巨佬. 废话不多说,看题: 题目大意 已知一个长度为n的序 ...
- 2018.09.28 bzoj1563: [NOI2009]诗人小G(决策单调性优化dp)
传送门 决策单调性优化dp板子题. 感觉队列的写法比栈好写. 所谓决策单调性优化就是每次状态转移的决策都是在向前单调递增的. 所以我们用一个记录三元组(l,r,id)(l,r,id)(l,r,id)的 ...
- [BZOJ4850][JSOI2016]灯塔(分块/决策单调性优化DP)
第一种方法是决策单调性优化DP. 决策单调性是指,设i>j,若在某个位置x(x>i)上,决策i比决策j优,那么在x以后的位置上i都一定比j优. 根号函数是一个典型的具有决策单调性的函数,由 ...
- BZOJ2216 Poi2011 Lightning Conductor 【决策单调性优化DP】
Description 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt( ...
- 算法学习——决策单调性优化DP
update in 2019.1.21 优化了一下文中年代久远的代码 的格式…… 什么是决策单调性? 在满足决策单调性的情况下,通常决策点会形如1111112222224444445555588888 ...
- BZOJ4899: 记忆的轮廓【概率期望DP】【决策单调性优化DP】
Description 通往贤者之塔的路上,有许多的危机. 我们可以把这个地形看做是一颗树,根节点编号为1,目标节点编号为n,其中1-n的简单路径上,编号依次递增, 在[1,n]中,一共有n个节点.我 ...
随机推荐
- 一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录
1.如果A表TID是自增长,并且是连续的,B表的ID为索引 select * from a,b where a.tid = b.id and a.tid>500000 limit 200; 2. ...
- 安装使用swoole
swoole首页:https://www.swoole.com/ 方法1:使用pecl安装 pecl install swoole 注意,php版本必须是7.0以及7.0以上的版本. 方法2:编译源码 ...
- centos yum install oracle java
How to install Java on CentOS 7 | Linuxizehttps://linuxize.com/post/install-java-on-centos-7/ CentOS ...
- Tomcat web.xml配置参数详解
Apache Tomcat Configuration Reference - The Context Containerhttps://tomcat.apache.org/tomcat-5.5-do ...
- vsconsole
一.安装 npm install vconsole 二. if (process.env.NODE_ENV === `development`) { const { logger } = requir ...
- 调整分区大小 转载--------------http://blog.csdn.net/perfectzq/article/details/73606119
centos7重新调整分区大小 centos 7 调整 root 和 home 的容量大小 查看磁盘的空间大小: df -h 备份/home : cp -r /home/ homebak/ 卸载 ...
- 关于Navicat连接虚拟机宝塔数据库
1.由于虚拟机安装的宝塔面板,目前没找到数据库安全配置文件,所以没能用Navicat连接数据库 2.在宝塔面板=>安全下 放行 3306 端口 即可以 连接成功 跟将bind-address = ...
- Java变量类型识别的3种方式
内容导览 反射方式,成员变量的类型判断 isInstance用法 利用泛型识别类型 测试类: package com.cxyapi.oo; import java.util.Date; import ...
- vscode git設置
1.git官网https://git-scm.com/download/win 链接下载:64-bit Git for Windows Setup,不要下载Portable,体积太大了: 如果git官 ...
- Appium之开发计算器自动化测试脚本Demo
1.依赖包 <!-- https://mvnrepository.com/artifact/io.appium/java-client --> <dependency> < ...