• 【bzoj4518】 Sdoi2016—征途


    http://www.lydsy.com/JudgeOnline/problem.php?id=4518 (题目链接)

    题意

      给出n个连续的整数,求将它们分成m段,求最小方差*m^2。

    Solution

      把m^2乘进去,然后就约掉了一大堆东西,我们用${f_{i,j}}$表示前j个数分成i组的最小值:

    $${f_{i,j}=Min{f_{i-1,k}+(S_i-S_k)^2}}$$

      显然这可以斜率优化。然后就斜率优化咯。

    细节

      最近很不爽,头晕炸了。。一道sb题写了2个小时。。。我真是zz

    代码

    // bzoj4518
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define inf 1<<30
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=3010;
    int q[maxn],n,m,p;
    LL s[maxn],f[2][maxn];
    
    double slope(int i,int j) {
    	return (double)(f[p^1][i]+m*s[i]*s[i]-f[p^1][j]-m*s[j]*s[j])/(s[i]-s[j]);
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int x,i=1;i<=n;i++) scanf("%d",&x),s[i]=s[i-1]+x;
    	for (int i=1;i<=n;i++) f[0][i]=m*s[i]*s[i];
    	for (int j=2;j<=m;j++) {
    		int l=1,r=0;p^=1;
    		for (int i=j-1;i<j;i++) q[++r]=i;
    		for (int i=j;i<=n;i++) {
    			while (l<r && slope(q[l],q[l+1])<=2*m*s[i]) l++;
    			f[p][i]=f[p^1][q[l]]+m*(s[i]-s[q[l]])*(s[i]-s[q[l]]);
    			while (l<r && slope(q[r-1],q[r])>slope(q[r],i)) r--;
    			q[++r]=i;
    		}
    	}
    	printf("%lld",f[p][n]-s[n]*s[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    汉语-词语:养生
    汉语-词语:道家美学
    汉语-词语:审美
    人物-书法家:王羲之
    人物-道家:庄子
    汉语-词语:含蓄
    关于finfo_file函数获取文件mime值验证出错的问题
    第一个Hello,OS World操作系统
    Lead软件项目半年感受
    Cts框架解析(15)-任务运行完
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6240277.html
Copyright © 2020-2023  润新知