CSP-S 2019 划分
Posted hock
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP-S 2019 划分相关的知识,希望对你有一定的参考价值。
( ext {划分})
将一个序列分为(m)段((m)自己决定())并且每一段的和递增 求(sum_{i=0}^m s_i ^ 2)
(s_i)为每一段的和
subtask1 ( ext {期望得分 36pts})
比较好想 (f[i][j])表示最后一段尾部端点尾(i) 头端点为(j) 的最小代价
[f[i][j] = max(f[j][k] + sqr((s[i] - s[j])))]
subtask2 ( ext {期望得分 64pts})
可以优化一下枚举(i,j)然后二分找到(k) 时间复杂度(O(n^2 log n))
subtask3 ( ext {期望得分 64pts})
可以证明如果一个区间大于前面的区间 且可以分为 ( ext {a b (pre <= a <= b}))
那么将他分开一定是最优的 那么对于一个(i) 我们去维护一个(f[i])并且使得(s[i] - s[f[i]])最小化 答案一定是最优的
我们可以((n^2))找到一个最优的(f[i])然后就得到了(64pts)的高分
std ( ext {期望得分 100pts})
暴力(O(n ^ 2))未免太暴力了 我们可以想满足条件 (s[i] - s[j] >= s[j] - s[f[j]])
移项可得(s[i] >= s[j] * 2 - s[f[j]]) 我们只需找到最后一个满足这个条件的值
然后(f[i] = j)就行了 这个东西可以用单调队列去写
int head = 1, tail = 1;
for (int i = 1; i <= n; i ++ ) {
while (head < tail && calc (q[head + 1]) <= s[i]) head ++ ;
g[i] = q[head];
while (head < tail && calc (q[tail]) >= calc (i)) tail -- ;
q[++tail] = i;
}
for (int i = n; i >= 1; i = g[i]) ans = (ans + sqr (s[i] - s[g[i]]));
分析
(36)比较( ext{navie})难度普及
(64) 分析性质 难度提高
(100) 用单调队列维护不难想 关键是前面一步的证明 难度提高+
以上是关于CSP-S 2019 划分的主要内容,如果未能解决你的问题,请参考以下文章