ZR24 Summer A Day5 | DP
CF808E Selling Souvenirs 加强
\(n\) 个物品的背包,\(V_i\in[1,4]\),\(w_i\le 10^9\),\(n\le 10^5\)。
基于值域枚举后进行贪心
观察到 \(\operatorname{lcm}(1,2,3,4)=12\),于是我们可以将重量为 \(1,2,3,4\) 的分别打包为重量为 \(12\) 的。比如 \(12\) 个重量为 \(1\) 的可以凑成一组,其他同理。但是会出现零散的也就是无法打包的部分,由于值域很小,直接枚举即可。
设 \(cnt_i\) 表示重量为 \(i\) 的拿了多少个。我们枚举 \(cnt_1 \bmod 12\),\(cnt_2\bmod 6\),\(cnt_3\bmod 4\),\(cnt_4\bmod 3\)。接着选最大的 \(cnt_1\bmod 12\) 个 \(1\),\(cnt_2\bmod 6\) 个 \(2\)...
这么处理之后剩下的就都是重量为 \(12\) 的大组了,可以贪心去取。
分治-闵可夫斯基和
直接背包没有凸性,但是在 \(\bmod (\operatorname{lcm}(1,2,3,4)=12)\) 意义下的每一个剩余系都具有凸性。
设 \(f_{i,k}\) 表示选了 \(12\times k+i\) 体积的物品,可以得到的最大价值。
我们可以采用分治,每个区间维护上述 \(12\) 的个凸函数,然后左右区间进行 \(12\times 12\) 次合并。
假设现在合并的是左 \(a\) 和右 \(b\),那么合并到大区间后就是 \(\to (a+b)\bmod 12\)。对于 \(k\) 那一维度可以做闵可夫斯基和。
CF1787H Codeforces Scoreboard
假设已经知道了哪些用 \(a_i\),哪些用 \(b_i-k_i\times t\),那么我们直接按照 \(k\) 从大到小排序,先选 \(k\) 大的,再选 \(k\) 小的,最后选那些 \(a_i\) 的就能保证最优。但是我们现在不知道选择了什么,可以先按照 \(k\) 降序排序,然后 dp,这样子就可以在决策的过程中符合上述贪心操作了。
\(dp_{i,j}\) 表示前 \(i\) 个题用了 \(j\) 个题是 \(b_i-k_i\times t\) 形式的所用最小时间。
这个形式很明显就是一个整体 dp 的形式,应该是要用大 DS 维护。
感性理解一下,这种加一个斜率为负的一次函数和常数取 \(\max\) 的东西应该是凸的。
打表/根据取 \(\max\) 的特性,可以得到 \(dp_{i,j}\) 对于每个 \(i\) 关于 \(j\) 是上凸的。
考虑 \(dp_{i,j}\) 的决策,
假设我们选择前者,就要满足
由于 \(dp\) 是上凸的,所以等式左边应该是单调递减的。等式右边也是单调的,所以可以直接二分找到交点。或者可以看成一条斜率为 \(-k_i\) 的直线去切 \(dp\) 的凸包。
假设我们找到了交点为 \(j=x_0\),
那么对于 \(j\le x_0\),我们要对于 \(dp\) 整体加 \(a_i\)。
对于 \(j\ge x_0\),我们要对于 \(dp\) 平移(因为转移脚标是 \(j-1\to j\))之后加一个一次函数 \(-k_i\times j+b_i\)。
有点难做,我们不妨维护其差分数组 \(g_{i,j}=dp_{i,j}-dp_{i,j-1}\)。
思考差分的变化,
前一段的区间加就是差分的单点加减。然后交接点的地方处理要小心点,就是对于 \(j=x_0+1\),此时 \(dp_{i,x_0}=dp_{i-1,x_0}+a_i,dp_{i,x_0+1}=dp_{i-1,x_0}+b_i-k_i\times j\),\(g_{i,x_0+1}=b_i-a_i-k_i\times j\)。
对于 \(j=x_0+2\),\(dp_{i,x_0+2}=dp_{i-1,x_0+1}+b_i-k_i\times (j+1)\),\(g_{i,x_0+2}=g_{i-1,x_0+1}-k\)。对于 \(j\) 更大的情况同理,这一部分就是平移之后后缀加一个 \(-k\)。
所以我们可以发现对于 \(g\) 的操作就是单点加,单点插入 (\(x_0+1\) 处),还有后缀加。
可以用平衡树维护,时间复杂度 \(O(n\log n)\)。
ABC305Ex Shoji
先思考段内权值,对于同一段内如何排序?这是经典的复合函数极值化顺序确定,可以用邻项交换法,发现按照 \(\dfrac{B}{A-1}\) 从小往大复合可以使得最后的权值尽可能小。
然后本题显然可以用 wqs 二分之后进行 DP。设 \(dp_i\) 表示前 \(i\) 个前的最优答案。
发现这个函数复合的增长是十分迅速的,至少也是 \(2^x\) 级别的,所以我们可以只取前 \(30\) 个点作为 dp 的决策点。
但是这题细节非常多。
首先,\(a_i=1\) 的点增长速度非常慢会影响我们上述取前 \(30\) 个点的正确性,可以单独处理,每次令花费上界 \(C\gets C-b_i\),然后把这个物品删除了就行了。
如果单纯是下凸函数代价 \(\le C\) 的点构成一个区间,不能直接二分,因为不满足单调性。可以找到通过 wqs 二分找到最小值点之后,往左右两边再次二分找到这个区间。而本题的下凸函数同时还是单调递减的,所以我们可以直接二分找到第一个代价 \(\le C\) 的点。
同时我们二分的判定条件不是操作次数,而是代价,所以应该最大化操作次数,因为每次划分是 \(-k\),故最后的权值其实是 \(dp_n+kx\),(其中 \(k<0\)),那么 \(x\) 越大的时候这个值越小。然后还需要处理三点共线,因为最大化操作次数,所以这个时候我们是找到了最右边的点,通过直线信息复原得到满足要求的最左边的点就行了。
还有一些细节是设置 \(+\infty\) 上面的,由于我们 wqs 二分的时候会给出一个 \(\delta\) 的代价,因此 DP 初始化和不合法区间的 \(+\infty\) 都应该设置为 \(>nC\) 的一个数字。
于是时间复杂度是 \(O(n\log^2 V)\)。
P9266 [PA 2022] Nawiasowe podziały
一道神仙题啊。
括号序列变成 \(\pm 1\) 前缀和,那么一个合法区间 \([l,r]\) 的判定是 \(s_{l-1}=s_r=\min\limits_{i=l-1}^rs_i\),其中区间最小值约束是为了防止中间右括号过多且在左括号左边。上述判定等价于对于序列 \(\{s_i\}\) 建立广义笛卡尔树之后,\(l-1\) 和 \(r\) 为某一层的极值点。
显然可以第一步 wqs 二分后,然后进行一个序列上的 DP。
容易证明 \(w\) 满足四边形不等式,因为 \(f\) 的转移具有决策单调性。采用决策单调性分治即可,同时在线求解 \(w\) 可以在 \(O(\log n)\) 的时间内通过括号树求解。直接做的时间复杂度是 \(O(n\log^2 n\log V)\)。
事实上可以做到单 \(\log\),原因是上述转移忽略了许多优美的结构,我们把这个 DP 的过程搬到广义笛卡尔树上去,做一个树形 DP。
我们进行如下约束:对于区间 \([l,r]\) 划分的时候必须在包含 \([l,r]\) 的极小广义笛卡尔树区间进行,因为这样子贡献更方便计算。
树上 DP 的时候设 \(f_u\) 表示 \(u\) 子树至少划分一次的最小代价,\(g_u\) 表示 \(u\) 子树不进行划分的代价。
于是我们的策略对于一个子树根节点 \(u\),提取其关键点(也就是区间最小值点)序列 \(\{v_i\}\)。我们对于 \(v\) 序列进行一个 DP,单次划分必须至少包含一个 \(v_i\),否则违反了上述原则。于是要么在当前节点管辖范围内进行划分,要么递归到子树小区间 \([v_i+1,v_{i+1}-1]\) 内进行划分再合并上来贡献 \(\min (f_s,g_s)\)。
假设一次划分 \([l,r]\) 包括了 \(l~v_i~v_{i+1}\dots v_j~r\),那么本层的贡献是 \(j-i+1\choose 2\),同时还有子树内部的贡献(注意由于区间最小值约束,这个贡献不能跨越某个 \(v_k\)),也就是 \([l,v_i)\cup (v_i,v_{i+1})\cup\dots (v_{j},r)\) 的内部不划分的贡献,除去首尾区间的贡献可以预处理,也就是子树内各层 \(c\choose{2}\) 之和,\(c\) 是某一层关键点个数,也就是对于 \(g\) 做一个前缀和预处理。但是 \([l,v_i)\) 和 \((v_j,r]\) 的贡献不方便快速求解,因为上文说了我们只对于 \(v\) 关键点序列进行 DP,无法考虑到内部的 \(l,r\) 这些小点。但是这里有一个巧妙的我们可以直接用 \(f_s\) 来解决,因为 \(f_s\) 本质是对于 \([v_{i}+1,v_{i+1}-1]\) 内部的一个划分,这样子内部划分出来的最左边的区间和最右边的区间可以去和外面相接,构成 \([l,v_{i})\) 或者 \((v_j,r]\) 这种区间。
于是我们对于关键点序列 \(\{v_i\}\) 进行 DP 的时候,设 \(dp_i\) 表示划分点 \(\in [v_{i-1},v_i)\) 且我们已经统计了 \([v_1,v_i)\) 贡献后的最小代价。
首先有不跨越关键点的划分 \(dp_{i}\gets dp_{i-1}+\min(f_s,g_s-x)\)。
接着有跨越关键点的转移,这里不需要付出 \(x\) 的代价了,因为在底层算 \(f\) 的时候已经划分过了。
直接转移是平方的,把 \(g\) 求和用前缀和表示,组合数拆成二次函数,可以利用斜率优化线性求解。
最后对于整个子树 \(u\) 还有两步转移: \(g_u=\sum g_s+{c\choose 2}\),对于 \(dp\to f\) 的转移类比上述 dp 的转移,因为最后一个关键点之后可能还有一小段序列,于是就假装我们在序列末尾多了一个虚点还是同理转移即可。
有一些细节就是,如果 \(j\) 取 \(0\) 这个虚点的时候,组合数应该是 \(i-j-1\choose{2}\),因为 \(0\) 不可以当成真正的关键点。还有斜率优化的时候,应该是双关键字(第二关键字为划分次数),所以第一个细节就是三点共线的时候如果新加点的划分次数比中间点的划分次数多,我们应该保留中间点(但是不能不加入新点,否则凸包形态就会不对了),否则踢掉中间点。同理查询移动指针的时候,遇到切线和某个斜率共线就不要移动了,因为根据上述加点原则里面共线点里面靠左的划分次数是更少的。哦如果凸包里面只有两个点的时候,还是会出一些问题,因为前两个点是直接加的,你不会判断它们的第二关键字,懒得改了,因为测试数据连上面那个都没卡,更别说这个了。
时间复杂度 \(O(n\log n)\)。
环状邮局系列
如果随机化断环为链的话,是单次采用决策单调性分治是 \(O(nk\log n)\),发现断点的个数至少是 \(\dfrac{n}{k}\) 个的,于是我们随机 \(O(\dfrac{n}{k})\) 次,所以最后是 \(O(n^2\log n)\) 的。环状邮局
太难了,这部分放弃了。
CF1842I Tenzing and Necklace
如果链状的,直接 wqs 二分+单调队列就行了。
先构造一组方案,然后根据相交 \(>\) 包含,发现其他方案的点必须是交错在初始方案中的,决策单调性分治。
Gym102268J Jealous Split
考虑固定相邻两段进行判定,这个时候不管怎么调整分界线,\(\max (m_i,m_{i+1})\) 就不变了,如果两端中 \(s_i-s_{i+1}>\max a\),我们可以不断把 \(i\) 段末尾的数放入第 \(i+1\) 段,直到出现合法。
我们发现如果能做调整,最后的 \(\sum s_i^2\) 会变小,那么 \(\sum s^2_i\) 最小的时候,就是不能调整了。
根据二次函数的凸性,我们可以 wqs 二分,然后斜率优化。
至于构造方案可以记录前缀 \(\max \min\) 拼接。
P9338 [JOISC 2023 Day3] Chorus
寻找性质的 dp 好题。首先一个序列能划分为若干个合唱队的充要条件是第 \(i\) 个 \(A\) 在第 \(i\) 个 \(B\) 前面。
考虑划分出 \(k\) 个合唱队,注意到第 \(i\) 个 \(A\) 一定和第 \(i\) 个 \(B\) 一组,所以匹配形式一定是第 \([l,r]\) 个 \(A\) 和第 \([l,r]\) 个 \(B\) 放在一组,于是我们需要对于 \([1,n]\) 划分成出 \(k\) 个区间 \([l,r]\),然后让第 \(l∼r\) 个 \(A\) 在第 \(l∼r\) 个 \(B\) 前面。
设 \(f_{i,j}\) 表示前 \(i\) 个位置里面划分出了 \(j\) 个区间,可以得到
设 \(w(l,r)\) 表示区间 \([l,r]\) 的调整代价,不难发现设第 \(i\) 个 \(A\) 前面有 \(c_i\) 个 \(B\),那么有$$w(l,r)=\sum\max(c_i-l+1,0)$$
直接暴力 dp 是 \(O(n^3)\) 的。可以发现 dp 的第二维关于 \(j\) 是具有凸性的,可以用 wqs 二分来去掉这一维度。
同时 \(w\) 是满足四边形不等式的,使用二分队列维护,时间复杂度 \(O(\log n\log V)\)。会被卡常。
其实 \(w\) 是可以去掉 \(\max\) 的,可以发现 \(w\) 是单调的,所以记 \(p_l\) 表示最小的位置满足 \(c_{p_l}-l+1\ge 0\),拆掉 \(\max\) 之后就是一个斜率优化的形式了,可以线性求解。于是总的时间复杂度就是 \(O(n\log n)\)。
Gym102331J Jiry Matchings
设 \(f_{u,i,0/1}\) 表示 \(u\) 子树内选择了 \(i\) 个匹配以及\(u\) 是否被选择的最大权值和。
直接使用树上背包是 \(O(nk)\) 的。很容易发现 \(f_{i,j}\) 是凸的,于是考虑使用闵可夫斯基和。
悲伤的是,优化之后的时间复杂度依然是 \(O(n^2)\) 的。因为单次合并的时间复杂度是 \(O(|A|+|B|)\),而不是 \(O(\min(|A|,|B|))\)。
对于凸函数的合并,一个一个并是一个很劣的策略。考虑一个更加优秀的方法:分治合并。
可以是我们的儿子都是一个一个加入的,如何分治合并?
待完成。
Gym102331H Honorable Mention
ZR2842
我们对于 \(0 1\) 做 \(+-1\) 前缀和。我们发现一个长度 \(>1\) 的 \(1\) 段是可以拆成多个小段的。
LOJ6289. 花朵
LOJ3661. 「2021 集训队互测」蜘蛛爬树
可以发现 \(u_x\to v_y\) 的路径必定 \(u_x\to w_x\to w_y\to v_y\),对于 \(w\) 的位置进行分类讨论,在 \(\mathrm{LCA}(u,v)\) 之内还是之外,将距离改为深度推式子。
假设 \(w\) 在 \(\mathrm{LCA}\) 之内且和 \(u\) 一个子树,那么就是
在确定 \(\mathrm{LCA(u,w)}\) 之后可以发现这是对于 \(w\) 相关的一个凸包。暴力跳 \(\mathrm{LCA}\) 的复杂度肯定是不对的,可以按照 P11330 [NOISG 2022 Finals] Grapevine 里面的 trick 暴力跳重链查询。
对于 \(w\) 在外面的情况同理。
可以维护凸包或者直接使用李超线段树来求解。
CF1534G A New Beginning
水题,不知道为啥评黑。
首先将切比雪夫距离转化为曼哈顿距离,就是单次的代价就是 \(\lvert X-x_i\rvert+\lvert Y-y_i \rvert\),其中每次只能往右上/右下走。我们的行走是没有代价的,所以肯定是走到一个尽可能优的点,对于任意路径发现曼哈顿距离最近的时候是走到某个点垂直于 \(x\) 轴的线上。
据此进行 DP,设 \(dp_{i,j}\) 表示在 \(x_i\) 位置的上纵坐标为 \(j\)。列出转移方程,
这是一个每次加上一次函数的图象,由于取 \(\min\) 操作,很显然其是下凸的函数,可以使用 Slope Trick 进行优化。
我们使用两个堆维护下凸函数的左半边和右半边,记为 \(L,R\)。
令 \(l=x_i-x_{i-1}\),首先 \(dp_{i-1,k}\) 和 \(|y_i-j|\) 是独立的,我们先处理前者,也就是\(\min\limits_{\lvert k-j\rvert\le l} dp_{i-1,k}\),观察函数图象,只需要对于 \(L\) 向左平移 \(l\),对于 \(R\) 向右平移 \(l\) 即可,这个打一个全局移动的标记就行了。然后就是全局 \(+|y_i-x|\) 的操作,分类讨论 \(y_i\) 与 \(L\) 最右端还有 \(R\) 最左端的大小关系,然后往堆中加入转折点(代表斜率变化)即可。由于求的是最小代价,我们直接维护下凸函数斜率 \(=0\) 的那一段的高度(函数值)即可。
时间复杂度 \(O(n\log n)\)。
P9521 [JOISC 2022] 京都观光
考虑 \((l,x)\to(r,y)\) 的路径可以 \((l,x)\to (r,x)\to (r,y)\),也可以 \((l,x)\to (l,y)\to (r,y)\)。
前者的代价是 \(b_x(r-l)+a_r(y-x)\),后者的代价是 \(a_l(y-x)+b_y(r-l)\)。前者比后者更优需要满足
可以发现这可以放到两个凸包上求解。单调栈建立对于 \(a,b\) 的凸包之后,每次选择斜率小的一边走。由于上述式子可以放到到任意局部,所以这是对的。
其实本质就是对于两个凸包进行闵可夫斯基和。

浙公网安备 33010602011771号