CF1527E, Partition Game
题意
定义一个数组的
给定一个
题解
设
状态转移:枚举
for j in [1, K + 1)
for i in [j, N + 1)
for k in [j - 1, i)
dp[i][j] = min(dp[i][j], dp[k][j - 1] + cost(k + 1, i))
复杂度为
发现线段树能维护区间
for j in [1, K + 1)
for i in [j, N + 1)
dp[i][j] = segtr_fk.min(j - 1, i - 1)
假设当遍历到
发现对于
而对于
for j in [1, K + 1)
for i in [j, N + 1)
segtr_fk.add(1, last[i], i - last[i])
dp[i][j] = segtr_fk.min(j - 1, i - 1)
发现每层的
for j in [1, K + 1)
segtr_fk.build(dp[][j-1])
for i in [j, N + 1)
segtr_fk.add(1, last[i], i - last[i])
dp[i][j] = segtr_fk.min(j - 1, i - 1)
代码
void solve()
{
int N, K;
std::cin >> N >> K;
std::vector<int> A(N + 1);
std::vector<int> pre(N + 1);
std::vector<int> last(N + 1);
for (int i = 1; i <= N; i++)
{
std::cin >> A[i];
last[i] = pre[A[i]];
pre[A[i]] = i;
}
std::vector<i64> dp(N + 1);
// 初始化 j = 1
for (int i = 1; i <= N; i++)
{
dp[i] = dp[i - 1];
if (last[i])
{
dp[i] += i - last[i];
}
}
for (int j = 2; j <= K; j++)
{
LazySegmentTree<i64, op, e, i64, mp, comp, id> f(dp);
for (int i = j; i <= N; i++)
{
if (last[i])
{
f.apply(1, last[i], i - last[i]);
}
dp[i] = f.prod(j - 1, i);
}
}
std::cout << dp[N] << '\n';
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】