https://atcoder.jp/contests/abc303/tasks
G - Bags Game
n包, i个x[i]钱
每次3选1
- 获得 最左/最右 一个
- 获得 最左/最右 (一共B个,可以分别取一部分) - A元
- 获得 最左/最右 (一共D个,可以分别取一部分) - C元
两人交替, 分别是X,Y, 求X-Y 的双方最优操作后的值,一个要最大,一个要最小
n 3000
xi,a,b,c,d, 1e9
2.5s
1024mb
我的思路
如果没有后两种
那就是经典的dp[l][r] =
从当前开始最优差值
dp[l][r] = max(x[l] - dp[l+1][r], x[r] - dp[l][r-1])
现在多了两种批量的情况
例如其中第二个方案就是 x[l...i] + x[j...r] - A - dp[i+1][j-1], len(l..i)+len(j..r) == B
但是注意到可以变换一下
x[l...r] - x[i+1..j-1] - A - dp[i+1][j-1], len(l..i)+len(j..r) == B
令 ndp[i..j] = x[i..j] + dp[i..j]
dp[l..r] = max(x[l] - dp[l+1][r],x[r]-dp[l][r-1],x[l..r] - A/C - ndp[i+1..j-1])
不妨设 第一种是 支付E=0元,取得F=1个
dp[l..r] = x[l..r] - min(A/C/E + ndp[i+1..j-1,A/C/E])
因此 需要一个 能够快速查询
[l...r]
区间内 A/C/E + min(ndp[len(l..r)-B/D/F])
即可
minndp[l..r]
可以通过minndp[l-1..r-1]
维护小根堆转移得到