• BZOJ3156 防御准备 动态规划 斜率优化


    原文链接http://www.cnblogs.com/zhouzhendong/p/8688187.html

    题目传送门 - BZOJ3156

    题意

      长为$n$的序列$A$划分,设某一段为$[i,j]$,则其花费为$A_j+sum_{k=i}^{j}(j-k)$。

      一种划分方式的花费就是他每一段的花费和。

      最小化花费。

      $nleq 10^6$

    题解

      斜率优化裸题。

      设$dp_i$表示序列前$i$项通过划分可以到的最小花费。

      则

      $$dp_i=min{dp_j+a_i+frac{(i-j)(i-j-1)}{2}}(0leq j<i)$$

      按照套路化简。

      得:

      $$dp_j+a_i+frac{(i-j)(i-j-1)}{2}\=dp_j+a_i+frac{j^2}2+frac j2+frac{i^2}2-frac i2-ij$$

      设$x_i=i,y_i=dp_i+frac{i^2}2+frac i2$,

      则原式

      $$=y_j-ix_j+frac{i^2}2-frac i2$$

      假设$k<j$且从$k$转移比$j$劣,那么:
      $$y_j-ix_j+frac{i^2}2-frac i2<y_k-ix_k+frac{i^2}2-frac i2$$
      $$Longrightarrow y_j-ix_j<y_k-ix_k$$

      $$Longrightarrow frac{y_j-y_k}{x_j-x_k}<i$$

      然后就是套路(其实前面也是套路……)

      参见这里

      但是这里为了避免精度问题,我们在计算$x$和$y$的时候都乘个$2$就可以了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1000005;
    int n,q[N],head=1,tail=0;
    LL a[N],id[N],dp[N],x[N],y[N];
    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    		scanf("%lld",&a[i]);
    	q[++tail]=0;
    	for (int i=1;i<=n;i++){
    		int j=q[head+1],k=q[head];
    		while (tail-head>0&&y[j]-y[k]<=(x[j]-x[k])*i)
    			head++,j=q[head+1],k=q[head];
    		j=k;
    		dp[i]=dp[j]+a[i]+1LL*(i-j-1)*(i-j)/2;
    		x[i]=i*2;
    		y[i]=dp[i]*2+i+1LL*i*i;
    		j=q[tail],k=q[tail-1];
    		while (tail-head>0&&(y[i]-y[j])*(x[j]-x[k])<=(y[j]-y[k])*(x[i]-x[j]))
    			tail--,j=q[tail],k=q[tail-1];
    		q[++tail]=i;
    	}
    	printf("%lld",dp[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    ssm整合之配置applicationContext-service.xml
    ssm整合之配置applicationContext-dao.xml
    ssm整合之mybatis配置文件SqlMapConfig.xml
    ssm整合之导包
    java BigDecimal工具类
    java中json依赖包
    Servlet+Json代码
    xstream+dom4j比较对象
    分析堆栈跟踪元素
    myeclipse搭建activemq 简单聊天
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3156.html
Copyright © 2020-2023  润新知