• [Hdu3507]Print Article(斜率优化)


    Description

    题意:给N个数,按顺序全部取走,每次取一段连续的区间,代价为((S[i]-S[j])^2+M)

    其中M为一个给定的常数,(S[i])为前缀和

    (Nleq 500000)

    Solution

    常规的方程:(dp[i]=min{dp[j]+(S[i]-S[j])^2+M}, j<i)

    (O(n^2))是过不了50万的,用斜率优化

    设有(k<j<i) 使得决策j更优,那么有

    (dp[j]+(S[i]-S[j])^2+M<dp[k]+(S[i]-S[k])^2+M)

    整理得 (frac{(dp[j]+S[j]^2)-(dp[k]+S[k]^2)}{(S[j]-S[k])}<2*S[i])

    (f[i]=dp[i]+S[i]^2),所以有(frac{f[j]-f[k]}{s[j]-s[k]}<2*S[i])

    此时决策j更优,反之决策k优

    易证(f[i])也单调递增,所以可用单调队列维护

    Code

    #include <cstdio>
    #include <algorithm>
    #define N 500010
    #define squ(x) ((x)*(x))
    using namespace std;
    
    int n,M,l,r,q[N],s[N],dp[N];
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    inline int f(int k,int j){return dp[j]+squ(s[j])-(dp[k]+squ(s[k]));}
    inline int g(int k,int j){return s[j]-s[k];}
    
    void DP(){
    	l=1,r=0;q[++r]=0;dp[0]=0;
    	for(int i=1;i<=n;++i){
    		while(l<r&&f(q[l],q[l+1])<=2*s[i]*g(q[l],q[l+1])) l++;
    		int j=q[l];
    		dp[i]=dp[j]+squ(s[i]-s[j])+M;
    		while(l<r&&f(q[r],i)*g(q[r-1],q[r])<f(q[r-1],q[r])*g(q[r],i)) r--;//保证斜率单调
    		q[++r]=i;
    	}
    }
    
    int main(){
      	while(~scanf("%d%d",&n,&M)){
    		for(int i=1;i<=n;++i) s[i]=s[i-1]+read();
    		DP();
    		printf("%d
    ",dp[n]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    nacos配置文件优先级
    springboot配置文件优先级(由高到低)
    设计模式七大设计原则
    docker安装mycat并实现mysql读写分离和分库分表
    docker部署mysql主从复制
    ideaui中java抬头
    数据定时备份
    docker容器安装vim
    JMeter的安装
    VUE项目中同时使用API代理与MockJs
  • 原文地址:https://www.cnblogs.com/void-f/p/8404311.html
Copyright © 2020-2023  润新知