zoukankan      html  css  js  c++  java
  • 【BZOJ3675】【APIO2014】序列分割

    题目:

    题目在这里

    思路:

    这题的DP不难, 但不要被题目描述迷惑了

    状态转移方程:

    [f_i = min { g_j + (sum_i - sum_j) * sum_j } ]

    (用了滚动数组, f是当前处理的, g是上一次得出的)

    可以用斜率优化

    [g_j + (sum_i - sum_j) * sum_j >= g_k + (sum_i -sum_k) * sum_k ]

    [g_j - g_k - {sum_j}^2 + {sum_k}^2 >= sum_i * (sum_k - sum_j) ]

    [{g_j - g_k - {sum_j}^2 + {sum_k}^2 over (sum_k - sum_j)} >= sum_i ]

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 100010;
    
    inline long long sqr(long long x) { return x * x; }
    
    long long a[N];
    long long sum[N];
    
    long long g[N], f[N];
    int Q[N], hd, tl;
    double calc(int j, int k) { return (double)(g[j]-g[k]+sqr(sum[k])-sqr(sum[j])) / (double)(sum[k]-sum[j]); }
    
    int main()
    {	int n, m;
    	scanf("%d %d", &n, &m);
    	for(int i=1; i<=n; i++)
    		scanf("%lld", &a[i]);
    	int tot = 0;
    	for(int i=1; i<=n; i++)
    		if(a[i] != 0) a[++tot] = a[i];
    	n = tot;
    	for(int i=1; i<=n; i++)
    		sum[i] = sum[i-1] + a[i];
    	for(int i=1; i<=m; i++)
    	{	hd = tl = 0;
    		for(int j=i; j<=n; j++)
    		{	while(hd < tl-1 && calc(Q[hd], Q[hd+1]) <= sum[j]) hd++;
    			f[j] = g[Q[hd]] + sum[Q[hd]] * (sum[j]-sum[Q[hd]]);
    			while(hd < tl-1 && calc(Q[tl-1], j) <= calc(Q[tl-2], Q[tl-1])) tl--;
    			Q[tl++] = j;
    		}
    		for(int j=i; j<=n; j++) swap(f[j], g[j]);
    	}
    	printf("%lld
    ", g[n]);
    	return 0;
    }
    
  • 相关阅读:
    Hadoop 解除 “Name node is in safe mode”
    ubuntu永久修改主机名
    ssh免密码登录
    su 和 su- 会影响环境变量
    卸载ubuntu自带openJDK,更改成自己的JDK版本
    ubuntu安装jdk 1.6
    147.Insertion Sort List
    145.Binary Tree Postorder Traversal
    144.Binary Tree Preorder Traversal
    143.Reorder List
  • 原文地址:https://www.cnblogs.com/2016gdgzoi509/p/8624780.html
Copyright © 2011-2022 走看看