• hdu3507,斜率优化dp


    斜率优化(dp)入门题。

    (ProblemLink)

    先从(n^2)(dp)开始

    (S_i=sum_{i=1}^n a_i)

    (f_i)为输出前(i)个的最小代价。

    显然有(f_i=min(f_j+(S_i-S_j)^2+M)(j<k))

    考虑对于点i。j比k((j>k))更优当且仅当

    (f_j+(S_i-S_j)^2<f_k+(S_i-S_k)^2)

    (f_j+S_j^2-2S_iS_j<f_k+S_k^2-2S_iS_k)

    ((f_j+S_j^2)-(f_k+S_k^2)<2Si(S_j-S_k))

    (huge frac {(f_j+S_j^2)-(f_k+S_k^2)}{(S_j-S_k)}<2Si)

    不妨设左式为(P(j,k))

    也就是说

    如果(P(j,k)<2Si),那么(j)就比(k)更优。

    我们发现如果把(f_i+S_i^2)这个东西看做(y),(S_i)看做(x)

    式子就变成了这样

    (huge frac{y_j-y_k}{x_j-x_k}<2Si)

    于是我们可以把每个决策点想象一个在二维平面直角坐标系上的点((x),(y))。

    这有什么用呢?

    我们发现,对于(i)来说,最优的决策就是那个斜率最小的点。

    我们就可以维护一个斜率递增的下凸壳,每次加入时更新。

    因为这里(Si)是单调递增的,用单调队列就可以维护了。

    否则就在凸壳上二分,找到小于(2Si)的最近的点。

    /*
    @Date    : 2019-07-31 08:27:46
    @Author  : Adscn (adscn@qq.com)
    @Link    : https://www.cnblogs.com/LLCSBlog
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define IL inline
    #define RG register
    #define gi getint()
    #define gc getchar()
    #define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    IL int getint()
    {
    	RG int xi=0;
    	RG char ch=gc;
    	bool f=0;
    	while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    	while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    	return f?-xi:xi;
    }
    template<typename T>
    IL void pi(T k,char ch=0)
    {
    	if(k<0)k=-k,putchar('-');
    	if(k>=10)pi(k/10,0);
    	putchar(k%10+'0');
    	if(ch)putchar(ch);
    }
    const int N=5e5+7;
    int s[N];
    int f[N];
    inline int sqr(int i){return i*i;}
    inline double X(int j,int k)
    {
    	return (f[j]+sqr(s[j])-f[k]-sqr(s[k]));
    }
    inline double Y(int j,int k)
    {
    	return (s[j]-s[k]);
    }
    int main(void)
    {
    	int n,m;
    	while(cin>>n>>m)
    	{
    		s[0]=0;
    		for(int i=1;i<=n;++i)s[i]=gi;
    		for(int i=1;i<=n;++i)s[i]+=s[i-1];
    		int l=1,r=0;
    		static int Q[N*2];
    		Q[++r]=0;
    		for(int i=1;i<=n;++i)
    		{
    			while(l<r&&X(Q[l+1],Q[l])<=2*s[i]*Y(Q[l+1],Q[l]))++l;
    			f[i]=f[Q[l]]+sqr(s[i]-s[Q[l]])+m;
    			while(l<r&&X(i,Q[r])*Y(Q[r],Q[r-1])<=X(Q[r],Q[r-1])*Y(i,Q[r]))--r;
    			Q[++r]=i;
    		}
    		cout<<f[n]<<endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    SQL Server 存储过程
    FindControl的详细介绍
    Transaction-SQL 游标
    硬盘安装工具nt6 hdd installer无法卸载的问题
    Some question about Source Tree
    java 简单加密
    java 多态与多重继承
    构造方法和方法的重载
    64位WIN7上安装11G R2 ,PLSQL的配置方法
    语录(排名不分先后)
  • 原文地址:https://www.cnblogs.com/LLCSBlog/p/11274535.html
Copyright © 2020-2023  润新知