• Problem 2082 过路费树链剖分


    裸题直接搞。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<vector>
    #include<stdlib.h>
    using namespace std;
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    typedef long long LL;
    const LL maxn = 55555;
    LL head[maxn];
    LL len, z;
    struct Node
    {
        LL next; LL to;
    }e[maxn * 2];
    LL top[maxn], son[maxn];
    LL father[maxn];
    LL size[maxn]; LL pos[maxn];
    LL deep[maxn];
    LL sum[maxn << 2];
    LL edge[maxn][10];
    
    void add(LL from, LL to)
    {
        e[len].to = to;
        e[len].next = head[from];
        head[from] = len++;
    }
    
    void init(LL x)
    {
        size[x] = 1; son[x] = 0;
        for (LL i = head[x]; i != -1; i = e[i].next){
            LL cc = e[i].to;
            if (father[x] == cc) continue;
            father[cc] = x; deep[cc] = deep[x] + 1;
            init(cc);
            size[x] += size[cc];
            if (size[son[x]] < size[cc])son[x] = cc;
        }
    }
    
    void dfs(LL x, LL tp)
    {
        pos[x] = ++z; top[x] = tp;
        if (son[x]) dfs(son[x], tp);
        for (LL i = head[x]; i != -1; i = e[i].next){
            LL cc = e[i].to;
            if (cc == father[x] || cc == son[x]) continue;
            dfs(cc, cc);
        }
    }
    
    
    void build(LL l, LL r, LL rt)
    {
        sum[rt] = 0;
        if (l == r) return;
        LL mid = (l + r) >> 1;
        build(lson); build(rson);
    }
    
    void up(LL rt)
    {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    
    void update(LL key, LL ans, LL l, LL r, LL rt)
    {
        if (l == r){
            sum[rt] = ans; return;
        }
        LL mid = (l + r) >> 1;
        if (key <= mid) update(key, ans, lson);
        else update(key, ans, rson);
        up(rt);
    }
    
    LL ask(LL L, LL R, LL l, LL r, LL rt)
    {
        if (L <= l&&r <= R) return sum[rt];
        LL mid = (l + r) >> 1;
        LL ans = 0;
        if (L <= mid) ans += ask(L, R, lson);
        if (R > mid) ans += ask(L, R, rson);
        return ans;
    }
    
    LL gao(LL x, LL y)
    {
        LL ans = 0;
        LL fx = top[x]; LL fy = top[y];
        while (fx != fy){
            if (deep[fx] < deep[fy]){
                swap(x, y); swap(fx, fy);
            }
            ans += ask(pos[fx], pos[x], 1, z, 1);
            x = father[fx]; fx = top[x];
        }
        if (x == y) return ans;
        if (deep[x]>deep[y]) swap(x, y);
        ans += ask(pos[son[x]], pos[y], 1, z, 1);
        return ans;
    }
    
    
    int main()
    {
        LL a, b, c;
        LL n, m;
        while (cin >> n >> m){
            memset(head, -1, sizeof(head));
            len = 0; z = 0;
            for (LL i = 1; i < n; i++){
                scanf("%I64d%I64d%I64d", &edge[i][0], &edge[i][1], &edge[i][2]);
                add(edge[i][0], edge[i][1]); add(edge[i][1], edge[i][0]);
            }
            deep[1] = 1;
            init(1); dfs(1, 1); build(1, z, 1);
            for (LL i = 1; i < n; i++){
                LL a = edge[i][0]; LL b = edge[i][1]; LL c = edge[i][2];
                if (deep[a]>deep[b]) swap(edge[i][0], edge[i][1]);
                update(pos[edge[i][1]], c, 1, z, 1);
            }
            for (LL i = 0; i < m; i++){
                scanf("%I64d%I64d%I64d", &a, &b, &c);
                if (a == 0){
                    edge[b][2] = c;
                    update(pos[edge[b][1]], c, 1, z, 1);
                }
                else{
                    LL t = gao(b, c);
                    printf("%I64d
    ", t);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    [编程题] 数组中的重复数字
    Redis数据结构之集合命令
    Redis数据结构之字符串命令
    Docker安装mysql
    后缀数组与字符串匹配
    牛客小白月赛11 Rinne Loves Edges
    牛客小白月赛11 Rinne Loves Xor
    牛客练习赛39 B.选点
    欧拉函数
    51 Nod 1700 首尾排序法
  • 原文地址:https://www.cnblogs.com/yigexigua/p/4077710.html
Copyright © 2020-2023  润新知