题解:P14481 星命定轨
非常好性质题。看一眼往区间 DP 想。假设一次操作选择的三个数,在原序列中对应:\(a_l,\ a_k,\ a_r\),其中 \(l<k<r\)。
因为这三个数在当前序列中已经连续了,所以:\([l+1,k-1]\) 以及 \([k+1,r-1]\) 中的数都已经被删掉。发现在这个过程中 \(a_k\) 会不断被区间中的最小值更新。所以最后这次操作获得的价值实际上是\({\min_{l<i<r}a_i}\) 与原来的 \(a_k\) 是多少无关。
接下来我们来找找这个题有哪些性质。
如果选择 \(a_l,a_r\) 作为一次操作的左右两端点,那么这次操作的收益是:\(c(l,r)=\min_{l<i<r}a_i\),于是原问题可以看成:
选择若干个区间 \((l,r)\),每个区间的价值为区间内部最小值,并且每个位置不能被重复使用。
如果直接做区间 DP,复杂度 \(O(n^3)\),显然不行。
我们再考虑两个相交的区间:\(l_1<l_2<r_1<r_2\),原来的收益为:\(c(l_1,r_1)+c(l_2,r_2)\),现在把它们换成:\((l_1,r_2)\) 和 \((l_2,r_1)\) 这两个区间。有\(c(l_1,r_2)=\min(c(l_1,r_1),c(l_2,r_2)) \),而 \(c(l_2,r_1)\ge\max(c(l_1,r_1),c(l_2,r_2))\),所以 \(c(l_1,r_2)+c(l_2,r_1)\ge c(l_1,r_1)+c(l_2,r_2)\),也就是说:
两个相交的区间可以换成两个不相交的区间,而且答案不会变差。
所以我们认定最优方案中的这些区间互不相交。
对于一个区间 \((l,r)\),它的贡献是:\(\min_{l<i<r}a_i\)
不妨把这个贡献直接挂到区间内部的最小值上。于是建立 \(a\) 的小根笛卡尔树。
对于笛卡尔树上的一个节点 \(x\):
- \(x\) 的子树对应原数组中的一段连续区间;
- \(a_x\) 是这段区间的最小值。
如果某个区间的最小值是 \(a_x\),就可以把这次操作的收益看成 \(a_x\)。
接下来我们就可以开始设计 DP 了。
考虑笛卡尔树上的节点 \(x\)。
定义 \(f[x][i][l][r]\) 表示考虑 \(x\) 的整棵子树,有 \(i\) 个位置暂时没有配对,左边界外的位置是否已经被使用为 \(l\),右边界外的位置是否已经被使用为 \(r\) 时能够得到的最大答案。其中,\(l,r\in{0,1}\),所以每个节点有 \(12\) 个状态。
接下来就是这个题比较厉害的一个点了,注意到最多只需要留下 2 个位置即为 \(i\in{0,1,2}\)。
假设当前有至少 \(3\) 个没有配对的位置。那么我们直接拿出其中三个完成一次操作即可,因为当前节点 \(x\) 是整个子树的最小值,所以这次操作至少可以获得 \(a_x\),而如果把这三个位置继续往下传,它们最终只可能在更大的节点处进行匹配。因为是小根堆笛卡尔树,越往下值越大。所以有三个空位置时,直接在当前节点配掉三个一定不会更差。因此 \({i\le2}\)。那么单从状态的设计上来看,是 \(O(n)\) 的。至于记录左右边界,假设 \(x\) 的子树在原数组中对应 \([L,R]\),那么一次以 \(a_x\) 为区间内部最小值的操作,它的左右端点并不一定都在 \([L,R]\) 里面。比如左端点可能是 \(L-1\) 右端点可能是 \(R+1\),所以需要记录 \(L-1\) 与 \(R+1\) 有没有被使用。
假设现在处理节点 \(x\)。左儿子状态 \(f[lson][lc][L_l][L_r]\),右儿子状态 \(f[rson][rc][R_l][R_r]\),其中 \(L_r\) 表示左子树的右边界是否被使用,\(R_l\) 表示右子树的左边界是否被使用。这两个位置实际上是同一个中间位置。所以,\(L_r=1,\ R_l=1\) 时显然不合法。
左右子树原本有 \(lc+rc\) 个。如果:\(L_r=0,\ R_l=0\),那么节点 \(x\) 自己也可以作为一个新的空位置。所以:\(cnt=lc+rc+[L_r=0][R_l=0]\)
接下来是转移,第一种转移,什么都不做,直接把空位置向上继续传,\(f[x][\min(cnt,2)][L_l][R_r]\) 更新为 \(f[lson]+f[rson]\) 即可。
第二种转移就是三个空位置配成一次操作,如果:\(cnt\ge3\),那么直接拿三个空位置配成一次操作。答案增加:\(a_x\),所以 \(cnt\) 变 \(cnt-3\) 了。
第三种转移则为使用左边界,如果:\(cnt\ge2\),并且左边界还没有使用,那么可以拿左边界和两个空位置完成一次操作。于是 \(cnt\) 变 \(cnt-2\) 并令 \(L=1\) 即可。
第四种转移则为使用右边界完全对称。如果 \(cnt\ge2\) 并且右边界还没有使用,那么 \(cnt\) 变为 $ cnt-2$ 并令 \(R=1\) 就行了。
最后,左右边界一起使用。如果:\(cnt\ge1\) 并且左右边界都没有使用,那么左空右可以直接组成一次操作。所以 \(cnt\) 变为 $ cnt-1$ 同时,
\(L=R=1\)
如果 \(x\) 是叶子,那么它自己可以作为一个没有配对的位置 \(
f[x][1][L][R]=0\) 同时也可以直接使用左右边界,获得 \(a_x\),所以
\(f[x][0][1][1]=a_x\)
初始化的时候要注意,留下一个或两个空位置是不可能的,赋值为 -inf 即可。
根节点没有左右边界,所以最终必须满足 \(L=R=0\),但是题目并不要求把所有数都删掉,所以最后可以剩下 \(0,1,2\) 个没有配对的位置。因此答案为三者的最大值。
接着,注意到 \(n\) 最大为 \(10^6\),所以不能使用递归 DFS(但是好像能过,题解区好多佬这么写),否则最坏情况下笛卡尔树退化成链,可能就爆栈。用数组保存遍历顺序,倒序进行 DP。复杂度为 \(O(n)\)。

浙公网安备 33010602011771号