[BZOJ 3675][Apio2014]序列分割

来源:互联网 发布:mac flash插件错误 编辑:程序博客网 时间:2024/04/30 16:36

斜率优化

如何压缩维数。

dp[i] = max(dp[j] + (s[i] - s[j]) * s[j])


dp[i] = max(dp[j] + s[i] * s[j] - sqr(s[j]));
如果k比j优且k>j
则有s[k] > s[j]
dp[j] + s[i] * s[j] - sqr(s[j]) < dp[k] + s[i] * s[k] - sqr(s[k])


(s[k] - s[j]) * s[i] > dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])


s[i] > (dp[j] - dp[k] - sqr(s[j]) + sqr(s[k])) / (s[k] - s[j])


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define maxn 100010using namespace std;int n, K;int a[maxn];long long dp[2][maxn], sqr[maxn], s[maxn];int cur;int q[maxn];double slop(int k, int j){return (double) (dp[cur][j] - dp[cur][k] - sqr[j] + sqr[k]) / (s[k] - s[j]);}void Transform(int x){int l = 1, r = 0, j;for(int i = x; i <= n; i ++){while(l < r && slop(q[l], q[l + 1]) < s[i])    l ++;j = q[l];dp[cur ^ 1][i] = dp[cur][j] + s[i] * s[j] - sqr[j];while(l < r && slop(q[r - 1], q[r]) > slop(q[r], i))    r --;q[++ r] = i;}}int main(){scanf("%d%d", &n, &K);int x, tot = 0;for(int i = 1; i <= n; i ++){scanf("%d", &x);if(x)a[++ tot] = x;}n = tot;for(int i = 1; i <= n; i ++){s[i] = s[i - 1] + a[i];sqr[i] = s[i] * s[i];}for(int i = 1; i <= K; i ++){Transform(i);cur ^= 1;}printf("%lld\n", dp[cur][n]);return 0;}


0 0
原创粉丝点击