zoukankan      html  css  js  c++  java
  • [WC2010]重建计划 长链剖分 + 线段树

    二分以后长链剖分 + 线段树, 扣了半天常数。

    好像还用啥nb迭代优化一下二分。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = (int)1e5 + 7;
    const double eps = 1e-9;
    
    int n, L, U;
    int head[N], edge_tot;
    int len[N], son[N], w[N];
    int in[N], dfs_clock;
    double tmp[N], add[N];
    double cost;
    bool ok;
    
    struct Edge {
        int to, w, nex;
    } e[N << 1];
    
    inline void addEdge(int u, int v, int w) {
        e[edge_tot].to = v;
        e[edge_tot].w = w;
        e[edge_tot].nex = head[u];
        head[u] = edge_tot++;
    }
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    
    struct Tree {
        double mx[N << 2], lazy[N << 2];
        void build(int l, int r, int rt) {
            lazy[rt] = 0;
            mx[rt] = -1e18;
            if(l == r) return;
            int mid = l + r >> 1;
            build(lson); build(rson);
        }
        void update2(int p, double val, int l, int r, int rt) {
            mx[rt] = max(mx[rt], val);
            if(l == r) return;
            int mid = l + r >> 1;
            if(p <= mid) update2(p, val, lson);
            else update2(p, val, rson);
        }
        double query(int L, int R, int l, int r, int rt) {
            if(R < l || r < L || R < L) return -1e18;
            if(L <= l && r <= R) return mx[rt];
            int mid = l + r >> 1;
            return max(query(L, R, lson), query(L, R, rson));
        }
    } Tree;
    
    void gao(int u, int fa) {
        son[u] = len[u] = 0;
        for(int o = head[u]; ~o; o = e[o].nex) {
            int v = e[o].to;
            if(v == fa) continue;
            w[v] = e[o].w;
            gao(v, u);
            if(len[v] > len[u]) {
                len[u] = len[v];
                son[u] = v;
            }
        }
        len[u]++;
    }
    
    void dfs1(int u, int fa) {
        in[u] = ++dfs_clock;
        if(son[u]) dfs1(son[u], u);
        for(int o = head[u]; ~o; o = e[o].nex) {
            int v = e[o].to;
            if(v == fa || v == son[u]) continue;
            dfs1(v, u);
        }
    }
    
    void dfs2(int u, int fa) {
        if(ok) return;
        add[u] = 0;
        if(son[u]) {
            dfs2(son[u], u);
            Tree.update2(in[u], -add[son[u]] - w[son[u]] + cost, 1, n, 1);
            add[u] = add[son[u]] + w[son[u]] - cost;
        }
        else {
            Tree.update2(in[u], 0, 1, n, 1);
        }
        int l = in[u] + L;
        int r = min(in[u] + len[u] - 1, in[u] + U);
        if(Tree.query(l, r, 1, n, 1) + add[u] >= 0.0) ok = true;
        for(int o = head[u], v, w; ~o && !ok; o = e[o].nex) {
            v = e[o].to, w = e[o].w;
            if(v == fa || v == son[u]) continue;
            dfs2(v, u);
            for(int i = 1; i <= len[v] && i <= U && !ok; i++) {
                int l = max(0, L - i), r = min(len[u] - 1, U - i);
                tmp[in[v] + i - 1] = Tree.query(in[v] + i - 1, in[v] + i - 1, 1, n, 1) + add[v] + w - cost;
                if(tmp[in[v] + i - 1] + Tree.query(in[u] + l, in[u] + r, 1, n, 1) + add[u] >= 0.0) {
                    ok = true;
                }
            }
            for(int i = 1; i <= len[v] && i <= U && !ok; i++) {
                Tree.update2(in[u] + i, tmp[in[v] + i - 1]- add[u], 1, n, 1);
            }
        }
    }
    
    int main() {
        scanf("%d%d%d", &n, &L, &U);
        for(int i = 1; i <= n; i++) head[i] = -1;
        for(int i = 1; i < n; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addEdge(u, v, w);
            addEdge(v, u, w);
        }
        gao(1, 0);
        dfs1(1, 0);
        double low = 0, high = 1000001, mid;
        for(int o = 0; o <= 30; o++) {
            mid = (low + high) / 2;
            cost = mid; ok = false;
            Tree.build(1, n, 1);
            dfs2(1, 0);
            if(ok) low = mid;
            else high = mid;
        }
        printf("%.3f
    ", (low + high) / 2);
        return 0;
    }
  • 相关阅读:
    安装node和npm
    安装git
    常用软件
    vscode常用插件
    git生成ssh key
    04.接口初始化规则与类加载器准备阶段和初始化阶段的意义
    03.编译期常量与运行期常量的区别与数组创建本质分析
    02.常量的本质含义与反编译及助记符
    01.类加载,连接与初始化过程
    HTTP 状态码大全
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11637583.html
Copyright © 2011-2022 走看看