zoukankan      html  css  js  c++  java
  • [CEOI2017] Building Bridges

    传送门

    Description

    (n)根柱子依次排列,每根柱子都有一个高度。第 (i) 根柱子的高度为 (h_i)

    现在想要建造若干座桥,如果一座桥架在第 ii 根柱子和第 jj 根柱子之间,那么需要 ((h_i-h_j)^2) 的代价。

    在造桥前,所有用不到的柱子都会被拆除,因为他们会干扰造桥进程。第 (i) 根柱子被拆除的代价为 (w_i),注意 (w_i)不一定非负,因为可能政府希望拆除某些柱子。

    现在政府想要知道,通过桥梁把第 (1) 根柱子和第 (n) 根柱子连接的最小代价。注意桥梁不能在端点以外的任何地方相交。

    Solution

    一道水题写了好久,小难受。。。

    发现那个(w_i)好烦,干脆最后全部加上个(sum _i),在成为桥柱的地方减掉相应的(w_i)

    关于斜率优化之前写的总结

    此题显然是需要(cdq)分治的,或者动态凸包

    按照惯例,(dp)题目是不会展现转移式子的,毕竟都很好写

    注意就是求斜率的时候一定要考虑斜率不存在的情况!!!


    Code 

    #include<bits/stdc++.h>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define reg register
    #define db long double
    #define ll long long
    #define ri reg int i
    #define int ll
    
    inline ll read()
    {
    	ll 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<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MN=1e5+5;
    int n,w[MN],X[MN],Y[MN],f[MN],sum;
    
    
    bool cmpl(int i,int j){return X[i]<X[j];}
    bool cmpr(int i,int j){return X[i]<X[j];}
    db calc(int i,int j){if(X[i]==X[j])return Y[i]<Y[j]?-1e18:1e18;return (db)(Y[i]-Y[j])/(X[i]-X[j]);}
    int sqr(int x){return x*x;}
    int cal(int i,int j){return f[j]+sqr(X[j]-X[i])-w[i];}
    
    
    int lrk[MN],rrk[MN];
    int q[MN],tl,hd;
    
    
    void cdq(int l,int r)
    {
    	if(l==r){Y[l]=f[l]+sqr(X[l]);return;}
    	
    	reg int mid=(l+r)>>1,i,j;
    	
    	cdq(l,mid);
    	
    	for(i=l;i<=mid;++i) lrk[i]=i;
    	std::sort(lrk+l,lrk+mid+1,cmpl);
    	for(i=mid+1;i<=r;++i) rrk[i]=i;
    	std::sort(rrk+mid+1,rrk+r+1,cmpr);
    	
    	for(tl=0,i=l;i<=mid;++i)
    	{
    		while(tl>1&&calc(q[tl],q[tl-1])>=calc(lrk[i],q[tl])) --tl;
    		q[++tl]=lrk[i];
    	}
    	
    	for(hd=1,i=mid+1;i<=r;++i)
    	{
    		while(hd<tl&&calc(q[hd+1],q[hd])<=(db)2.*X[rrk[i]]) ++hd;
    		f[rrk[i]]=min(f[rrk[i]],cal(rrk[i],q[hd]));
    	}
    	
    	cdq(mid+1,r);
    }
    
    signed main()
    {
    	n=read();reg int i;
    	
    	for(i=1;i<=n;++i) X[i]=read(),f[i]=1ll<<60;
    	
    	for(i=1;i<=n;++i) w[i]=read(),sum+=w[i];
    		
    	f[1]=-w[1];
    	
    	cdq(1,n);
    	
    	printf("%lld
    ",sum+f[n]);
    	
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    单例模式
    dubbo环境搭建
    树莓派Zero W无键盘无屏幕初始化
    Arduino连接MPU6050陀螺仪
    Raspberry Pi3驱动Oled ssh1106屏
    SonarQube 7.7默认数据库连接方法
    解决SonarQube启动时直接挂掉问题
    解决sonar的ES无法启动问题
    Jenkins自动打包并部署(以java -jar形势运行)
    python3中OpenCV imwrite保存中文路径文件
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10673525.html
Copyright © 2011-2022 走看看