zoukankan      html  css  js  c++  java
  • [BZOJ4518][SDOI2016]征途

    bzoj
    luogu

    description

    你要把一个长度为(n)的数列划分为(m)段,最小化每一段之和的方差。
    (1 le m le n le 3000)

    sol

    设第(i)段的和为(S_i),数列中的元素总和为(X),那么

    [mbox{ans}=msum_{i=1}^m(S_i-frac Xm)^2=msum_{i=1}^mS_i^2-X^2 ]

    所以只需要考虑最小化(sum_{i=1}^mS_i^2)就好啦。
    这个显然可以做(O(nm))的斜率优化。
    然后这里的答案也显然是凸的,所以可以凸优化一下。
    于是我们就愉快地用(O(nlog X))的复杂度过掉了一道(n=3000)的题啦。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 30005;
    struct info{
    	int f,k;
    	info operator + (const info &b) const
    		{return (info){f+b.f,k+b.k};}
    }dp[N];
    int n,m,s[N],q[N],hd,tl;
    int y(int i){return dp[i].f+s[i]*s[i];}
    void solve(int c){
    	hd=tl=0;
    	for (int i=1;i<=n;++i){
    		while (hd<tl&&y(q[hd+1])-y(q[hd])<2*s[i]*(s[q[hd+1]]-s[q[hd]])) ++hd;
    		dp[i]=dp[q[hd]]+(info){(s[i]-s[q[hd]])*(s[i]-s[q[hd]])+c,1};
    		while (hd<tl&&1ll*(y(i)-y(q[tl]))*(s[q[tl]]-s[q[tl-1]])<1ll*(y(q[tl])-y(q[tl-1]))*(s[i]-s[q[tl]])) --tl;
    		q[++tl]=i;
    	}
    }
    int main(){
    	n=gi();m=gi();
    	for (int i=1;i<=n;++i) s[i]=s[i-1]+gi();
    	int l=0,r=s[n]*s[n],mid;
    	while (l<r){
    		mid=l+r>>1;solve(mid);
    		if (dp[n].k<=m) r=mid;else l=mid+1;
    	}
    	solve(r);int S=dp[n].f-m*r;
    	printf("%lld
    ",1ll*S*m-1ll*s[n]*s[n]);
    	return 0;
    }
    
  • 相关阅读:
    Spring.Net的AOP的通知
    Spring.Net的IOC入门
    Unity依赖注入使用
    C#dynamic关键字(1)
    多线线程async与await关键字
    C#面试题
    MangoDB的C#Driver驱动简单例子
    安装vuecli和使用elememtUi
    再也不怕aop的原理了
    easyui实现多选框,并且获取值
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9428844.html
Copyright © 2011-2022 走看看