题解:P10236 [yLCPC2024] D. 排卡
算法分析
首先,由于要求最大化下面的式子:
其次,由于双端队列需要控制两端的位置,所以显然要使用区间 DP。
状态设计
首先记录一个区间的左、右端点,所以第一步令 fl, r 表示 a 中 [l, r] 这一区间最大的贡献。
但是,[l, r] 可能由 [l + 1, r] 或 [l, r − 1] 得来,无法固定,所以需要记录 [l, r] 是由哪个区间得来的。
能不能记录这个数的下标呢?这是不行的,因为这样空间复杂度就会变为 O(n3),铁定爆炸。
根据之前的描述,[l, r] 只有两种得到的可能性,所以可以将第三维表示为 0/1:
- fl, r, 0 表示当前区间为 [l, r],且是先弹出 al;
- fl, r, 1 表示当前区间为 [l, r],且是先弹出 ar。
这样,我们就可以进行状态转移了。
状态转移
声明:下面的转移方程中暂时先忽略取模。
考虑 fl, r, 0 如何转移。
由于 fl, r, 0 由 [l + 1, r] 得来,所以此时先弹出的是 al,即 bi = al。
由于 [l + 1, r] 不固定,所以我们需要分类讨论:
- [l + 1, r] 弹出的是 l + 1,那么 (bi, bi + 1) = (al, al + 1),所以结果是 fl + 1, r, 0 + alal + 1;
- [l + 1, r] 弹出的是 r,那么 (bi, bi + 1) = (al, ar),所以结果是 fl + 1, r, 1 + alar。
所以 fl, r, 0 = max {fl + 1, r, 0 + alal + 1, fl + 1, r, 1 + alar}
或许给张图能更好理解(?
![f[l][r][0] 的转移 图解](C:\Users\77017\Desktop\学习笔记\题解\题解:P10236 [yLCPC2024] D. 排卡.assets\cq46gcl9.png)
接下来考虑 fl, r, 1 如何转移,与上面的转移同理。
fl, r, 1 由 [l, r − 1] 得来,所以 bi = ar。
- [l, r − 1] 弹出的是 l,那么 bi + 1 = al;
- [l, r − 1] 弹出的是 r − 1,那么 bi + 1 = ar − 1。
所以 fl, r, 1 = max {fl, r − 1, 0 + aral, fl, r − 1, 1 + arar − 1}
转移细节
初始化
全部赋值为 0,因为一个空的区间显然结果为 0。
最终答案
最终结果为 max {f1, n, 0, f1, n, 1},即整个数组第一次弹出左/右端点的答案中的最大值。
代码实现
实现细节
本题中特别规定 00 = 0,所以快速幂中需要特判;
区间长度至少为 2,否则弹出后是空的,没有意义。
f 数组要开为
long long类型:由于仅在快速幂的时候取模,求和是不取模,那么每个值最大为 998, 244, 352,需要求和 n − 1 次,998, 244, 352 × (nmax − 1) = 997, 246, 107, 648 > 109,所以要开
long long。
完整代码
1 |
|
