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

    Description

    题库链接

    从山顶上到山底下沿着一条直线种植了 (n) 棵老树。当地的政府决定把他们砍下来。为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。

    木材只能朝山下运。山脚下有一个锯木厂。另外两个锯木厂将新修建在山路上。你必须决定在哪里修建这两个锯木厂,使得运输的费用总和最小。假定运输每公斤木材每米需要一分钱。询问计算最小运输费用。

    (1leq nleq 20000)

    Solution

    记从山顶向下重量做一个前缀和为 (w_i),第 (i) 棵树到山底的距离为 (d_i),所有树到底端的距离乘重量的和为 (sum)

    枚举两个锯木厂位置 (i,j(j<i))。显然答案就是 (max{sum-w_j imes d_j-(w_i-w_j) imes d_i})

    由于 (w)(d) 的单调性相反,于是这个式子是可以斜率优化的,把 (j) 优化掉就可以 (O(n)) 求解了。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 20000+5;
    
    int n, w[N], d[N], f[N], q[N], head, tail, tmp, ans;
    
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d%d", &w[i], &d[i]);
        for (int i = n; i >= 1; i--) d[i] += d[i+1], tmp += w[i]*d[i];
        for (int i = 1; i <= n; i++) w[i] += w[i-1];
        q[head = tail = 1] = 1;
        for (int i = 2; i <= n; i++) {
            while (head < tail && 1ll*w[q[head+1]]*d[q[head+1]]-w[q[head]]*d[q[head]]
             >= 1ll*d[i]*(w[q[head+1]]-w[q[head]])) ++head;
            ans = max(ans, w[q[head]]*d[q[head]]-d[i]*w[q[head]]+w[i]*d[i]);
            while (head < tail && 1ll*(w[i]*d[i]-w[q[tail-1]]*d[q[tail-1]])*(w[i]-w[q[tail]])
             <= 1ll*(w[i]*d[i]-w[q[tail]]*d[q[tail]])*(w[i]-w[q[tail-1]])) --tail;
            q[++tail] = i;
        }
        printf("%d
    ", tmp-ans);
        return 0;
    }
  • 相关阅读:
    SpinLock 实现
    支持正则或通配符的hashmap
    HTTP报文
    Protostuff序列化
    【转】轻量级分布式 RPC 框架
    Servlet 3特性:异步Servlet
    Web服务器的工作原理
    《恰如其分的软件架构:风险驱动的设计方法》——读书笔记
    Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
    Java Socket常见异常处理 和 网络编程需要注意的问题
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/12262130.html
Copyright © 2011-2022 走看看