[题解] P15038 「chaynOI R2 T3」合并同类项
definieren · · 题解
二操作是一操作的特殊情况,因此先让
一个暴力的做法是记
注意到剩下的包都有
观察到我们上面的转移其实是只关心和为
事实上确实是这样的,期望应该是
这样的话我们可以将状态更改为
具体来说,转移需要用
一种优化方法是对于左端点相同的和为
#include <bits/stdc++.h>
using i64 = long long;
constexpr i64 inf = 1E18;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int n, k, x, y;
std::cin >> n >> k >> x >> y;
y = std::min(x, y);
std::vector<int> a(n);
for (int i = 0; i < n; i ++) {
std::cin >> a[i];
}
std::vector<std::array<int, 2>> rs;
std::vector<std::vector<int>> vec(n);
for (int r = 1; r <= n; r ++) {
int sum = 0;
for (int l = r - 1; l >= 0; l --) {
((sum += a[l]) >= k) && (sum -= k);
if (sum == 0 || (l == 0 && r == n)) {
vec[l].push_back(rs.size());
rs.push_back({l, r});
}
}
}
const int m = rs.size();
std::vector<i64> f(m);
std::vector<std::array<i64, 2>> g(n + 1);
for (int i = 0, l, r = rs[0][1]; i < m; i ++) {
if (i == 0 || rs[i][1] != r) {
r = rs[i][1];
l = r - 1;
g[r][1] = inf;
g[r][0] = 0;
}
while (l >= rs[i][0]) {
g[l][1] = std::min(g[l + 1][0], g[l + 1][1] + x);
g[l][0] = g[l + 1][0] + x;
for (auto j : vec[l]) {
if (rs[j][1] <= r && j != i) {
g[l][0] = std::min(g[l][0], f[j] + g[rs[j][1]][0] + y);
g[l][1] = std::min(g[l][1], f[j] + g[rs[j][1]][1] + y);
g[l][1] = std::min(g[l][1], f[j] + g[rs[j][1]][0]);
}
}
-- l;
}
f[i] = g[rs[i][0]][1];
l = rs[i][0];
}
std::cout << f.back() << '\n';
return 0;
}