决策单调性学习笔记
\(\large \rm 定义\)
\(\quad\)假设有 \(p_1\leqslant p_2\leqslant p_3\leqslant p_4.\)
\(\quad\)则 \(c_{p_1,p_3}+c_{p_2+p_4}\leqslant c_{p_1,p_4}+c_{p_2,p_3}\) 被称为四边形不等式。
\(\quad\)假设一个问题满足四边形不等式,那么它的决策点有单调性。
\(\large\rm 证明\)
\(\quad\)假设有如下问题 :现在有一个序列,我们要将其分割开来,分割一段 \([l,r]\) 的代价是 \(c_{l,r}\),求最小代价。
\(\quad\)设 \(F_i\) 表示将前 \(i\) 个位置分割完毕的最小代价,显然有暴力转移 :
\(\quad\)设 \(F_i\) 的决策点为 \(p_i.\) 假设存在 \(x>y,p_x<p_y.\)
\(\quad\)根据最优决策的定义写出这个位置的转移式 :
\(\quad\)有 \(p_x<p_y<y<x\),根据四边形不等式得到 :
\(\quad\)两不等式相加,得到 :
\(\quad\)与前文矛盾,故不存在 \(x>y,p_x<p_y\),即满足决策单调性。
\(\large\rm 区间形式\)
\(\quad\)在实际做题中,我们经常遇到这样的 \(\rm DP\) 方程 :
\(\quad\)我们考虑将四边形不等式推广到二维形式。
\(\quad\)定理 \(1\) :若 \(w\) 满足四边形不等式,并且对于任意 \(a\leqslant b\leqslant b\leqslant c\leqslant d\),有 \(w_{a,d}\geqslant w_{b,c}\),则 \(f\) 也满足四边形不等式。
\(\quad\)定理 \(2\) :设 \(p_{i,j}\) 表示 \(f_{i,j}\) 的决策点,若 \(f\) 满足四边形不等式,则对于任意 \(i<j\),有 \(p_{i,j-1}\leqslant p_{i,j}\leqslant p_{i+1,j}.\)
\(\quad\)例题 :\(\rm [NOI1995] 石子合并\)
\(\large\rm 有单峰性\)
\(\quad\)这个性质结合决策单调性有均摊转移复杂度 \(\Theta(1)\) 的做法 :
\(\quad\)记录一个指针表示当前的决策点,由于决策单调性所以它不会往回跳。进入每一层之后如果后面的决策点更优就跳到后面的决策点,根据单峰性这样一定不会漏掉解。
\(\quad\)跳的次数是状态级别的,故转移均摊 \(\Theta(1).\)
\(\large\rm 仅有相邻层之间转移\)
\(\quad\)这是一类特殊的二维 \(\rm DP\),仅有相邻层之间的转移,没有同层之间的转移,同时满足决策单调性。
\(\quad\)一般这种 \(\rm DP\) 的时间复杂度是 \(\Theta(n^3)\) 的,每次转移需要枚举前一层的所有点。
\(\quad\)我们发现一个性质,在同一层中,先枚举哪一个是无关紧要的,因为同一层之间不会发生转移。
\(\quad\)于是可以考虑分治,先转移 \(mid\),得到其最优决策为 \(p\),然后就可以将区间划分开,\([l,mid)\) 和 \((mid,r]\) 分别对应 \([tl,p]\) 和 \([p,tr].\)
\(\quad\)这样分治时间复杂度 \(\Theta(n\log n).\)
\(\quad\)例题 :\(\rm [SDOI2016]征途\)
\(\large\rm 贡献难算\)
\(\quad\)首先有例题 :存在一个长度为 \(n\) 的序列,要将它划分成 \(k\) 段,每段的价值被定义为不同的元素个数,要求最大化贡价值和。
\(\quad n\leqslant 3.5\times 10^4,k\leqslant 50.\)
\(\quad\)首先有一个 \(\Theta(n^3k)\) 的暴力 \(\rm DP\),设 \(dp_{i,j}\) 表示当分到 \(i\) 时已经分了 \(j\) 段的最大价值,有转移式 :
\(\quad\)其中 \(cnt_{l,r}\) 表示从 \([l,r]\) 中不同颜色的个数,单次计算需要 \(\Theta(n).\)
\(\quad\)我们发现只在相邻层之间发生转移,并且满足决策单调性(直观理解就是分得越多越容易亏),于是可以使用之前提到的分治法。
\(\quad\)这样看起来是优化到 \(\Theta(n^2k\log n)\),但我们考虑计算贡献的具体过程。我们每次只会计算 \(dp_{mid}\) 的值,每次询问一个区间 \([i,mid]\) 的不同元素个数,可以考虑固定右端点移动左端点,容易发现移动次数是当前的分治区间长度,于是总移动次数不会超过 \(n\log n\),故时间复杂度实际上为 \(\Theta(nk\log n).\)
\(\quad\)例题 :\(\rm [P5574]任务分配问题\)
\(\large\rm 斜率优化\)
\(\quad\)假设 \(\rm DP\) 方程长成这种形式 :
\(\quad\)即贡献为一个仅与 \(i\) 有关的式子加上一个仅与 \(j\) 有关的式子加上一个与两者都有关的乘积形式再加上一个常数,那么可以使用斜率优化。
\(\quad\)我们发现 \(dp_i,(i)',C\) 都与决策点的选择无关,于是可以把它们看作常数,将仅与 \(j\) 有关的式子放在一边,可以得到方程 :
\(\quad\)我们发现这是一次函数的形式,考虑构造平面,平面上有一些点,形如 \(((j),dp_j+(j)').\) 我们发现,如果用一条斜率为 \(-(i)\) 的直线经过某个点,那么截距为 \(dp_i-(i)'-C.\) 由于我们要最大化 \(dp_i\),等价于最大化这个截距,所以用这根斜率为 \(-(i)\) 的直线从上到下平移,第一个碰到的点就是决策点。
\(\quad\)于是现在问题就变成了维护一个凸包,我们发现有三种情况 :
-
当加入点按照横坐标单调递增的顺序,并且询问点单调递增时,可以直接维护单调队列,加入点对比队尾斜率,取答案从队首即可。
-
当加入点按照横坐标单调的顺序时可以维护一个单调队列,每次加入时对比斜率,取答案二分。
-
当加入点无序时直接用平衡树 \((std :: set)\) 维护,用 \(lower\_bound\) 查找插入点,然后向左右两边依次弹出,取答案也使用 \(lower\_bound.\)
\(\quad\)例题 :\(\rm [HNOI2008]玩具装箱TOY\),\(\rm [SDOI2016]征途\)
\(\large \rm 二分队列\)
\(\quad\)若 \(\rm DP\) 方程形如 :
\(\quad\)根据决策单调性的推论,任何两个点 \(i,j(i<j)\) 之间都存在一个点 \(k\),在 \(k\) 之前一段转移点为 \(i\),在 \(k\) 之后某一段转移点为 \(j.\)
\(\quad\)我们发现如果能快速计算 \(w_{i,j}\),那么就能 \(\Theta(\log n)\) 计算两个点 \(i,j\) 之间的决策分界点。
\(\quad\)我们发现所有相邻决策点的分界点可以用单调队列维护,具体来说 :
-
求当前的最优决策时判断一下队首和队次首谁更优,若队首最优则决策点为队首,否则决策点为队次首,并且将当前队首弹出。
-
加入一个点时判断它是否能比队尾更快地替换掉队次尾,若能,则弹出队尾,重复操作。
\(\quad\)这样就可以快速地维护相邻点的决策分界点了。
\(\quad\)时间复杂度 \(\Theta(n\log n).\)
\(\quad\)例题 :\(\rm [NOI2009]诗人小G\)
\(\large\rm 二分栈\)
\(\quad\)有些题可能会有这样的奇怪性质 :每个决策点只会被自己前面的点反超。
\(\quad\)我们发现某个决策点会经历这样的过程 :一开始就比前面的优(否则就相当于一开始就被别人反超了),然后在最优决策的地方呆一会儿,最后被某个点反超。
\(\quad\)严格来说这根本不算决策单调性,但是仍然可以用二分栈来维护,因为两点的优劣仍旧可以 \(\Theta(\log n)\) 对比。具体来说 :
- 加入一个点时,若其比堆顶劣,则直接扔掉,若其比堆顶优,则留下。
- 每一轮判断一下堆次顶是否比堆顶优,优则将堆顶弹出。
\(\quad\)这样堆顶就一直是当前转移的决策点。
\(\quad\)例题 :\(\rm [POI2011]Lightning Conductor\)
\(\large\rm SMAWK算法\)
\(\quad\)咕咕咕 \(......\)
原文地址:https://www.cnblogs.com/C-C-A/p/15116458.html
- iOS textfield实现一行的数字限制,超出进行弹框
- android https安全连接
- 第二章 正则表达式位置匹配攻略
- 从网络上下载省份城市名称并存入文件然后进行读取省份城市
- android 应用模式之mvp
- Android网络请求框架之Retrofit实践
- iOS 跳转到应用所在的App Store市场
- 第一章 正则表达式字符匹配攻略
- js最新手机号码、电话号码正则表达式
- iOS afnetworking最新版报错 没有AFHTTPRequestOperationManager类了
- Android Service学习之本地服务
- iOS .pch文件的使用
- CountDownTimer说明及使用
- UiTextField对输入的长度进行限制并提示用户还可输入的长度
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CS学习笔记 | 20、通过Socks转发的方法
- 构建的抽象
- 低成本个人建站系列二 —— 使用 Hexo+GitHub 搭建个人免费博客
- 42图揭秘,「后端技术学些啥」
- R-ggTimeSeries | ggplot2: 热力日历图
- R-wordcloud: 词云图
- 直播APP源码是如何实现音视频同步的
- 动态规划算法练习(5)--medium
- phpstudy漏洞分析原因到修复
- 哈?命令注入外带数据的姿势还可以这么骚?
- 记一次曲折的RCE挖掘
- pytest文档49-命令行参数--tb的使用
- pytest文档50-命令行参数--durations统计用例运行时间
- pytest文档51-内置fixture之cache使用
- pytest文档53-命令行实时输出错误信息(pytest-instafail)