zoukankan      html  css  js  c++  java
  • [CEOI2004]锯木厂选址

    题目

    思路

    (dis[i])表示i到山脚的距离,(sum[i])表示前i个木材的重量和,(tot)为不建锯木厂的代价

    假设分别建在(i,j)位置((i<j)),那么有(ans=min(tot−dis[j]∗sum[j]−dis[i]∗(sum[i]−sum[j])))

    化简得:(frac{dis[j]*sum[j]-dis[k]*sum[k]}{sum[j]-sum[k]} > dis[i])

    维护上凸壳即可

    Code

    #include<bits/stdc++.h>
    #define N 20005 
    using namespace std;
    int n,w[N],d[N],dis[N],sum[N],tot;
    int q[N],l=1,r=0,ans=2000000001;
    
    template <class T>
    void read(T &x)
    {
    	char c;int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
    }
    
    double k(int x,int y) {return ((double)dis[x]*sum[x]-(double)dis[y]*sum[y])/(sum[x]-sum[y]);}
    int main()
    {
    	read(n);
    	for(int i=1;i<=n;++i) read(w[i]),read(d[i]);
    	for(int i=1;i<=n;++i) sum[i]=sum[i-1]+w[i];
    	for(int i=n;i>=1;--i) dis[i]=dis[i+1]+d[i];
    	for(int i=n;i;--i) tot+=dis[i]*(sum[i]-sum[i-1]);
    	for(int i=1;i<=n;++i)
    	{
    		while(l<r && k(q[l],q[l+1])>dis[i]) ++l;
    		ans=min(ans,tot-dis[q[l]]*sum[q[l]]-dis[i]*(sum[i]-sum[q[l]]));
    		while(l<r && k(i,q[r-1])<k(i,q[r])) --r;
    		q[++r]=i;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    LeetCode
    已知二叉树的先序遍历和中序遍历序列求后序遍历序列
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    LeetCode
    TCP协议的基本规则和在Java中的使用
    Java中UDP协议的基本原理和简单用法
    LeetCode
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11674166.html
Copyright © 2011-2022 走看看