zoukankan      html  css  js  c++  java
  • [WC2010]重建计划

    给定一颗带边权的树,求一条边数在 ([L, R]) 之间的路径,并使得路径上边权的平均值最大。输出这个最大平均值。

    (n leq 10^5)

    同中位数 [Codeforces150E] Freezing with Style

    二分答案 (ans),每个边权减去 (ans),转换为判断是否存在路径的边权和非负。

    这里是长链剖分的解法,点分治的见上一篇。

    #include <bits/stdc++.h>
    #define dbg(...) std::cerr << "33[32;1m", fprintf(stderr, __VA_ARGS__), std::cerr << "33[0m"
    template <class T, class U>
    inline bool smin(T &x, const U &y) { return y < x ? x = y, 1 : 0; }
    template <class T, class U>
    inline bool smax(T &x, const U &y) { return x < y ? x = y, 1 : 0; }
    using LL = long long;
    using PII = std::pair<int, int>;
    
    constexpr int N(1e5 + 5);
    constexpr double EPS(1e-6);
    int n, l_, r_;
    int fa[N], f[N], son[N], val[N];
    std::vector<PII> g[N];
    void dfs1(int x) {
      for (auto [y, z] : g[x]) {
        if (y == fa[x]) {
          continue;
        }
        fa[y] = x;
        dfs1(y);
        if (smax(f[x], f[y] + 1)) {
          son[x] = y;
          val[x] = z;
        }
      }
    }
    struct Node {
      Node *ls, *rs;
      double max, add;
      void pushdown() {
        if (add) {
          if (ls) ls->add += add, ls->max += add;
          if (rs) rs->add += add, rs->max += add;
          add = 0;
        }
      }
      void pushup() {
        assert(rs);
        max = ls ? std::max(ls->max, rs->max) : rs->max;
      }
    } t[N << 2], *ptr;
    void ins(Node *&o, int l, int r, int x, double y) {
      if (!o) {
        o = ptr++;
        o->ls = o->rs = nullptr;
        o->max = -1e9;
      }
      o->pushdown();
      smax(o->max, y);
      if (l == r) {
        return;
      }
      int m = l + r >> 1;
      x <= m ? ins(o->ls, l, m, x, y) : ins(o->rs, m + 1, r, x, y);
    }
    void update(Node *o, int l, int r, int x, int y, double z) {
      if (!o) return;
      if (x <= l && r <= y) {
        o->add += z;
        o->max += z;
        return;
      }
      // assert(l < r);
      o->pushdown();
      int m = l + r >> 1;
      if (x <= m) update(o->ls, l, m, x, y, z);
      if (y > m) update(o->rs, m + 1, r, x, y, z);
      o->pushup();
    }
    double ask(Node *o, int l, int r, int x, int y) {
      if (!o || x > r || y < l) {
        return -1e9;
      }
      if (x <= l && r <= y) {
        return o->max;
      }
      o->pushdown();
      int m = l + r >> 1;
      return std::max(ask(o->ls, l, m, x, y), ask(o->rs, m + 1, r, x, y));
    }
    Node *root[N];
    double average;
    bool dfs2(int x, int dep) {
      root[x] = nullptr;
      if (son[x]) {
        if (dfs2(son[x], dep + 1)) return true;
        root[x] = root[son[x]];
        update(root[x], 0, dep + f[x], dep + 1, dep + f[x], val[x] - average);
      }
      ins(root[x], 0, dep + f[x], dep, 0);
      if (ask(root[x], 0, dep + f[x], dep + l_, dep + r_) > EPS) {
        return true;
      }
      for (auto [y, z] : g[x]) {
        if (y == fa[x] || y == son[x]) {
          continue;
        }
        if (dfs2(y, 0)) return true;
        static double d[N];
        std::function<void(Node*, int l, int r)> dfs = [&](Node *o, int l, int r) {
          assert(o);
          if (l == r) {
            d[l] = o->max;
            return;
          }
          o->pushdown();
          int m = l + r >> 1;
          dfs(o->ls, l, m), dfs(o->rs, m + 1, r);
        };
        dfs(root[y], 0, f[y]);
        for (int i = 0; i <= f[y]; i++) {
          if (d[i] + z - average + ask(root[x], 0, dep + f[x], dep + l_ - i - 1, dep + r_ - i - 1) > EPS) {
            return true;
          }
        }
        for (int i = 0; i <= f[y]; i++) {
          ins(root[x], 0, dep + f[x], dep + i + 1, d[i] + z - average);
        }
      }
      return false;
    }
    int main() {
      std::ios::sync_with_stdio(false);
      std::cin.tie(nullptr);
      std::cin >> n >> l_ >> r_;
      double l = 0, r = 0;
      for (int i = 1, x, y, z; i < n; i++) {
        std::cin >> x >> y >> z;
        g[x].emplace_back(y, z);
        g[y].emplace_back(x, z);
        smax(r, z);
      }
      dfs1(1);
      while (r - l > EPS) {
        average = (l + r) / 2;
        ptr = t;
        if (dfs2(1, 0)) {
          l = average;
        } else {
          r = average;
        }
      }
      printf("%.3f", l);
      return 0;
    }
    
  • 相关阅读:
    字段与表的对应关系
    java初学代码,还不太熟练
    编程学习心得
    ps中经常遇到的问题
    R语言矩阵运算加速
    写代码过程中一些数字推理公式
    EXCEL中常用的函数
    css样式中常见的属性
    R语言的基本矩阵运算
    excel常用的函数
  • 原文地址:https://www.cnblogs.com/HolyK/p/14238126.html
Copyright © 2011-2022 走看看