agc032d 解题报告
Sol1
考虑操作在干什么,本质是把一个数往左或往右插入到任意位置。我们考虑最终的形态,设最终每个数的位置分别为 \(b_i=i\),每次操作相当于对于一个区间的 \(i\),某个 \(b_{p_i}\) 单点修改,剩下的整体 +1/-1,直接这么做是困难的,因为一次操作影响的数很多,而且不好只根据结果得到每个数往哪边插入。
一个很有想象力的事情是,我们把一次插入改成只修改一个点的 \(b_{p_i}\),而其它点不变,那么把 \(p_i\) 插入到 \((x,x+1)\) 之间就取 \((x,x+1)\) 间的任意一个实数作为 \(b_{p_i}\),也就是说将 \(b\) 从 \([n]\) 扩展到实数轴上,从而每次操作就是对 \(b\) 的单点修改,要求变为 \(b\) 递增,且最后只要看 \(b_i\) 和 \(i\) 的大小关系就知道 \(i\) 怎么操作。
此时只要把实数轴划分为若干段 \([j,j+1)\),\(f_{i,j}\) 表示考虑到 \(b_1,\dots,b_i\),\(b_i\in[j,j+1)\) 的最小代价,那么转移根据 \(b_i\) 填在 \(j\) 还是 \((j,j+1)\) 转移即可,前缀 \(\min\) 优化后时间复杂度 \(\mathcal{O}(n^2)\)。
总结:为什么会想到扩域?原本的位置,是离散的资源,会被相互挤占,而本身排序,插入就是只考虑相对顺序的事情,我们只关心大小关系,扩域后正好满足了要求。下次遇到只关系大小顺序的题也可以考虑扩域。
Sol2
考虑最后没有操作的数一定是一个上升子序列,先固定一下这个子序列 \(a_1,a_2,\dots,a_m\),然后对于剩下的数 \(i\),容易根据确定的子序列中是否存在 \(a_j<i,p_{a_j}>p_i\) 和 \(a_j>i,p_{a_j}<p_i\) 来判断 \(p_i\) 往哪边走,而如果不存在 \(j\) 满足这两个条件中的任意一个,把 \(i\) 加进子序列一定不劣。
于是可以 DP,\(f_i\) 表示 \([1,i]\) 中 \(i\) 作为最后一个不操作的元素的最小代价,选择上一个数 \(j\),对于 \((j,i)\) 中的数,只根据和 \(p_i\) 的大小关系决定操作类型一定是不劣的,于是容易确定每个 \(j\) 的贡献。时间复杂度 \(\mathcal{O}(n^2)\)。
总结:考察最后不会被操作的子序列,然后就可以确定每个位置的操作,这也是一种常见的思路。

浙公网安备 33010602011771号