有 \(n\) 个数构成的序列 \({a_i}\),要将它划分为 \(k\) 段,定义每一段的权值为这段中 \((i,j) \ s.t. \ i<j,\ a_i=a_j\) 的个数,求一种划分方案,使得各段的权值和最小。 \(n \leq 10^5, k \leq min(n,20), a_i \leq n\)

设 \(f[i][j]\) 表示将 \(a_{1..j}\) 分为 \(i\) 段的最小价值,则很容易得到转移方程

\[f[i][j]=\min (f[i-1][k]+cost(k+1,j)) \ \ \ (k<j)
\]

暴力转移是 \(O(n^2 k)\),但这里有决策单调性,即 \(p_j\) 为 \(f[i][j]\) 的最优转移点(如果有多个就取最左边的),那么对于任意 \(k<j\) 一定有 \(p_k \leq p_j\)

注:形如 \(f_i = min/max_{j=1}^{i-1} g_j + w_{i,j}\),记 \(f_i\) 的最优决策点为 \(p_i\),即 \(f_i\) 从 \(g_{p_i} + w_{i,p_i}\) 处转移最优,如果满足 \(p_i \leq p_{i+1}\),则称该方程满足决策单调性

(不想证明可以先写个暴力打表然后一眼看规律)

所以我们整体二分来加速转移

考虑我们当前求解一段区间 \([l,r]\),所有 \(f_{i,j},\ j \in [l,r]\) 的最优决策点在 \([L,R]\) 之间。

对于 \([l,r]\) 的中点 \(mid\),可以暴力扫一遍 \([L,R]\),找到最优决策点 \(k\)

那么由于决策单调,所有 \(f_{i,j},\ j \in [l,mid]\) 的决策则落在 \([L,k]\) 上,所有 \(f_{i,j},\ j \in [mid+1,r]\) 的决策则落在 \([k,R]\) 上

总体时间复杂度 \(O(kn \log n)\)

因为某个循环边界写宽了然后就TLE了

#include <bits/stdc++.h>
using namespace std; #define int long long
const int N = 1000005;
int n,m,f[N],g[N],a[N],buc[N]={1,0},cnt;
signed pl,pr; inline void push(signed x) {
cnt+=buc[x];
buc[x]++;
} inline void pop(signed x) {
buc[x]--;
cnt-=buc[x];
} void trans(signed l,signed r) {
while(l<pl) pl--, push(a[pl]);
while(r>pr) pr++, push(a[pr]);
while(l>pl) pop(a[pl]), pl++;
while(r<pr) pop(a[pr]), pr--;
//cout<<l<<" "<<r<<" "<<cnt<<endl;
} void solve(int l,int r,int L,int R) {
int mid=(l+r)/2;
int mx=1e18,k=0;
for(int i=L;i<=min(R,mid-1);i++) { //!
trans(i+1,mid);
if(g[i]+cnt<mx) {
mx=g[i]+cnt;
k=i;
}
}
f[mid]=mx;
if(l<r) {
solve(l,(l+r)/2-1,L,k); //!
solve((l+r)/2+1,r,k,R);
}
} signed main() {
ios::sync_with_stdio(false);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++) {
trans(1,i);
f[i]=g[i]=cnt;
//<<g[i]<<" ";
}//cout<<endl;
for(int i=2;i<=m;i++) {
solve(1,n,1,n);
for(int j=1;j<=n;j++) g[j]=f[j];
/*for(int j=1;j<=n;j++) {
cout<<f[j]<<" ";
}
cout<<endl;*/
}
cout<<f[n];
}

Wannafly Camp 2020 Day 3F 社团管理 - 决策单调性dp,整体二分的更多相关文章

  1. Wannafly Camp 2020 Day 2B 萨博的方程式 - 数位dp

    给定 \(n\) 个数 \(m_i\),求 \((x_1,x_2,...,x_n)\) 的个数,使得 \(x_1 \ xor\ x_2\ xor\ ...\ xor\ x_n = k\),且 \(0 ...

  2. BZOJ_4609_[Wf2016]Branch Assignment_决策单调性+带权二分

    BZOJ_4609_[Wf2016]Branch Assignment_决策单调性+带权二分 Description 要完成一个由s个子项目组成的项目,给b(b>=s)个部门分配,从而把b个部门 ...

  3. BZOJ_5311_贞鱼_决策单调性+带权二分

    BZOJ_5311_贞鱼_决策单调性+带权二分 Description 众所周知,贞鱼是一种高智商水生动物.不过他们到了陆地上智商会减半. 这不?他们遇到了大麻烦! n只贞鱼到陆地上乘车,现在有k辆汽 ...

  4. BZOJ4426 :最大生产率(贪心+决策单调性DP)

    题意:给出N个人,现在让你分P组,每组的工作效率是最小结束时间-最大开始时间,要求每一组的效率的正数,求最大效率和.N<1000 思路: 把包含至少一个其他的分到A组:否则到B组. A组的要么单 ...

  5. CF321E Ciel and Gondolas 【决策单调性dp】

    题目链接 CF321E 题解 题意:将\(n\)个人分成\(K\)段,每段的人两两之间产生代价,求最小代价和 容易设\(f[k][i]\)表示前\(i\)个人分成\(k\)段的最小代价和 设\(val ...

  6. BZOJ2216 [Poi2011]Lightning Conductor 【决策单调性dp】

    题目链接 BZOJ2216 题解 学过高中数学都应知道,我们要求\(p\)的极值,参变分离为 \[h_j + sqrt{|i - j|} - h_i \le p\] 实际上就是求\(h_j + sqr ...

  7. 洛谷 P3515 [ POI 2011 ] Lightning Conductor —— 决策单调性DP

    题目:https://www.luogu.org/problemnew/show/P3515 决策单调性... 参考TJ:https://www.cnblogs.com/CQzhangyu/p/725 ...

  8. LOJ2074/2157 JSOI2016/POI2011 Lightning Conductor 决策单调性DP

    传送门 我们相当于要求出\(f_i = \max\limits_{j=1}^{n} (a_j + \sqrt{|i-j|})\).这个绝对值太烦人了,考虑对于\(i>j\)和\(i<j\) ...

  9. Wannafly Winter Camp 2020 Day 5C Self-Adjusting Segment Tree - 区间dp,线段树

    给定 \(m\) 个询问,每个询问是一个区间 \([l,r]\),你需要通过自由地设定每个节点的 \(mid\),设计一种"自适应线段树",使得在这个线段树上跑这 \(m\) 个区 ...

随机推荐

  1. LeetCode 684. Redundant Connection 冗余连接(C++/Java)

    题目: In this problem, a tree is an undirected graph that is connected and has no cycles. The given in ...

  2. Integer缓存机制-基本数据类型和包装类型-自动拆装箱

    Integer缓存机制 总结: 1.jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,所以只要在缓存范 ...

  3. 杭电-------2044一只小蜜蜂(C语言写)

    #include<stdio.h> ] = { }; long long divide(int n) { ) { ; } ) { return a[n]; } ) + divide(n - ...

  4. 修改kali软件源并配置网络

    一.配置kali使用xshell连接 查看ssh服务状态 # service ssh status 开启ssh服务 # service ssh start 修改ssh配置文件 # vi /etc/ss ...

  5. vue路由--命名视图

    有时候想同时(同级)展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,这个时候命名视图就派上用场了.你可以在界面中拥有多个单独命名的视图, ...

  6. JMeter接口测试-循环读取库的用户信息

    前言 如何实现循环读取数据库的用户信息,并传递到下一个登录请求呢,下面我们一起来学习吧!在之前我们已经学会了利用JMeter连接数据库了,具体操作可以看我之前的随笔JMeter接口测试-JDBC测试 ...

  7. Http API触发小程序云函数案例

    1.创建云函数 在云开发中创建云函数(sum,调用需要两个参数:a.b): 2.invokeCloudFunction触发云函数 const request = require('request'); ...

  8. 论AMD内核如何使用Android Studio虚拟机

    其实之前和老师求证过AMD内核要用虚拟机的话应求助第三方模拟器(不然速度太慢)或直接使用真机测试,当时拿着虚拟机的报错简单搜索了下只翻到了一个用谷歌第三方工具的(检索时关键词不对的锅),觉得麻烦就没去 ...

  9. Git的基本使用 -- 文件的添加、撤销、对比、删除

    显示当前工作区.暂存区.仓库的状态 git status 当工作区的所有文件都提交到仓库,并和仓库保持一致时 有修改的文件时,会显示有改动的文件,并提示如何提交这些修改 添加到暂存区,还未提交到仓库时 ...

  10. DolphinScheduler源码分析之任务日志

    DolphinScheduler源码分析之任务日志 任务日志打印在调度系统中算是一个比较重要的功能,下面就简要分析一下其打印的逻辑和前端页面查询的流程. AbstractTask 所有的任务都会继承A ...