• Codeforces 838 B


    B - Diverging Directions

    思路:

    用dfs序+线段树维护子树中距离(从1到u,再从u到1)的最小值

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
    //head
    
    const int N = 2e5 + 5;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    int L[N], R[N], anc[N][20], deep[N], f[N], b[N], bb[N], head[N], cnt = 1, now = 1;
    LL tree[N<<2], lazy[N<<2], a[N];
    struct edge {
        int from, to, w, nxt;
    }edge[N];
    void add_edge(int u, int v, int w) {
        edge[cnt].from = u;
        edge[cnt].to = v;
        edge[cnt].w = w;
        edge[cnt].nxt = head[u];
        head[u] = cnt++;
    }
    
    void push_up(int rt) {
        tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
    }
    void push_down(int rt) {
        lazy[rt<<1] += lazy[rt];
        lazy[rt<<1|1] += lazy[rt];
        tree[rt<<1] += lazy[rt];
        tree[rt<<1|1] += lazy[rt];
        lazy[rt] = 0;
    }
    void build(int rt, int l, int r) {
        if(l == r) {
            tree[rt] = a[f[l]];
            return ;
        }
        int m = l+r >> 1;
        build(ls);
        build(rs);
        push_up(rt);
    }
    void update(int L, int R, int v, int rt, int l, int r) {
        if(L <= l && r <= R) {
            tree[rt] += v;
            lazy[rt] += v;
            return ;
        }
        if(lazy[rt]) push_down(rt);
        int m = l+r >> 1;
        if(L <= m) update(L, R, v, ls);
        if(R > m) update(L, R, v, rs);
        push_up(rt);
    }
    LL query(int L, int R, int rt, int l, int r) {
        if(L <= l && r <= R) return tree[rt];
        if(lazy[rt]) push_down(rt);
        int m = l+r >> 1;
        LL ans = INF;
        if(L <= m) ans = min(ans, query(L, R, ls));
        if(R > m) ans = min(ans, query(L, R, rs));
        push_up(rt);
        return ans;
    }
    void dfs(int u) {
        L[u] = now;
        f[now] = u;
        for (int i = head[u]; ~i; i = edge[i].nxt) {
            int v = edge[i].to;
            anc[v][0] = u;
            for (int j = 1; j < 20; j++) anc[v][j] = anc[anc[v][j-1]][j-1];
            deep[v] = deep[u] + 1;
            now++;
            a[v] = a[u] - b[u] + edge[i].w + b[v];
            dfs(v);
        }
        R[u] = now;
    }
    int lca(int u, int v) {
        if(deep[u] < deep[v]) swap(u, v);
        for (int i = 19; i >= 0; i--) if(deep[anc[u][i]] >= deep[v]) u = anc[u][i];
        if(u == v) return u;
        for (int i = 19; i >= 0; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
        return anc[u][0];
    }
    int main() {
        int n, q, ty, u, v, w;
        mem(head, -1);
        scanf("%d %d", &n, &q);
        for (int i = 1; i < n; i++) {
            scanf("%d %d %d", &u, &v, &w);
            add_edge(u, v, w);
        }
    
        for (int i = 1; i < n; i++) {
            scanf("%d %d %d", &u, &v, &w);
            b[u] = w;
            bb[i] = u;
        }
    
        for (int i = 0; i < 20; i++) anc[1][i] = 1;
        dfs(1);
        build(1, L[1], R[1]);
        while(q--) {
            scanf("%d %d %d", &ty, &u, &v);
            if(ty == 1) {
                if(u >= n) {
                    int nod = bb[u-n+1];
                    int add = v - b[nod];
                    update(L[nod], L[nod], add, 1, L[1], R[1]);
                    b[nod] = v;
                }
                else {
                    int nod = edge[u].to;
                    int add = v - edge[u].w;
                    update(L[nod], R[nod], add, 1, L[1], R[1]);
                    edge[u].w = v;
                }
            }
            else {
                int l = lca(u, v);
                LL ans = INF;
                if(l == u) {
                    LL dis1 = query(L[u], L[u], 1, L[1], R[1]) - b[u];
                    LL dis2 = query(L[v], L[v], 1, L[1], R[1]) - b[v];
                    ans = dis2 - dis1;
                }
                else {
                    LL dis1 = query(L[u], R[u], 1, L[1], R[1]) - (query(L[u], L[u], 1, L[1], R[1]) - b[u]);
                    LL dis2 = query(L[v], L[v], 1, L[1], R[1]) - b[v];
                    ans = dis1 + dis2;
                }
                printf("%lld
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    高精度计算
    c++ sort
    算法分类小结
    二叉树层序遍历
    clion windows c++环境配置 mingw
    kafka,filebeat 配置
    centos7 源码安装mysql5.7
    如何优雅的生成及遍历python嵌套字典
    Java Swing 绝对布局管理方法,null布局【图】
    python3.4+pymssql 中文乱码问题解决
  • 原文地址:https://www.cnblogs.com/widsom/p/9530854.html
Copyright © 2020-2023  润新知