zoukankan      html  css  js  c++  java
  • 树链剖分+BIT

    树链剖分+BIT - FZU 2082 - 过路费

    核心思路:

    1. 边权转化为点权:树上某一条边可以唯一转化为子节点的点权
    2. BIT维护单点修改+区间查询

    注意本题有多组输入,每组样例需要重新init

    #include <cstdio>
    #include <vector>
    #include <cstdlib>
    
    using namespace std;
    
    const int N = 5e4+5;
    
    int n, m;
    int a;
    int b, c;
    
    
    struct Node{
        int v;
        int d;
        Node(){};
        Node(int _v,int _d){
            v = _v;
            d = _d;
        }
    };
    
    vector<Node> edges[N];
    
    vector<Node> vec(1);
    
    int head[N];
    int fa[N];
    int dep[N];
    int heavy_son[N];
    int dfs_id[N];
    int dfs_begin[N];
    int dfs_end[N];
    
    int w[N];   // 节点i到其父节点的边的边权
    
    int tree[N];
    
    int dfs1(int cur, int prev, int depth){
        fa[cur] = prev;
        dep[cur] = depth;
        int tot_size = 1, cur_size = 0,max_size = 0, max_root = 0;
    
        for(vector<Node>::iterator it = edges[cur].begin(); it != edges[cur].end(); ++it){
            if(it->v == prev) continue;
            w[it->v] = it->d;  // 节点i到其父节点的边的边权
            cur_size = dfs1(it->v, cur, depth+1);
            tot_size += cur_size;
            if(cur_size > max_size){
                max_size = cur_size;
                max_root = it->v;
            }
        }
        heavy_son[cur] = max_root;
        return tot_size;
    }
    
    void dfs2(int cur, int prev, int head_node, int& id){
        head[cur] = head_node;
        dfs_id[cur] = id++;
    
        if(heavy_son[cur]){
            dfs2(heavy_son[cur], cur, head_node, id);
        }
        for(vector<Node>::iterator it = edges[cur].begin(); it != edges[cur].end(); ++it){
            if(it->v == prev || it->v == heavy_son[cur]) continue;
            dfs2(it->v, cur, it->v, id);   
        }
        dfs_begin[cur] = dfs_id[cur];
        dfs_end[cur] = id-1;
    }
    
    
    void build_lct(){
        int id = 1;
        dfs1(1, 0, 1);
        dfs2(1, 0, 1, id);
    }
    
    int low_bit(int x){
        return -x & x;
    }
    
    int query(int pos){
        int ans = 0;
        while(pos >= 1){
            ans += tree[pos];
            pos -= low_bit(pos);
        }
        return ans;
    }
    
    void modify(int pos, int v){
        int delta = v - query(pos) + query(pos-1);
        while(pos <= n){
            tree[pos] += delta;
            pos += low_bit(pos);
        }
    }
    
    
    
    int query_lct(int a, int b){
        int ha, hb;
        int ans = 0;
        while(1){
            ha = head[a];
            hb = head[b];
            if(ha == hb){
                a = dfs_id[a];
                b = dfs_id[b];
                if(a > b) swap(a, b);
                ans += query(b) - query(a);
                break;
            }else{
                if(dep[ha] < dep[hb]){
                    swap(a, b);
                    swap(ha, hb);
                }
                ans += query(dfs_id[a]) - query(dfs_id[ha]-1);
                a = fa[ha];
            }
        }
        return ans;
    }
    
    void init(int n){
        for(int i = 1; i <= n; ++i){
            edges[i].clear();
        }
        vec.clear();
        vec.push_back(Node());
    
        int head[N];
        for(int i = 1; i <= n; ++i){
            heavy_son[i] = 0;
        }
        for(int i = 0; i < n; ++i){
            tree[i] = 0;
        }
    }
    int main(){
        while(scanf("%d%d", &n, &m)!=EOF){
            init(n);
            for(int i = 1; i < n; ++i){
                scanf("%d%d%d", &a, &b, &c);
                edges[a].push_back(Node(b, c));
                edges[b].push_back(Node(a, c));
                vec.push_back(Node(a, b));
            }
    
            build_lct();
            for(int i = 1; i <= n; ++i){
                modify(dfs_id[i], w[i]);
            }
    
            for(int i = 1; i < n; ++i){
                if(fa[vec[i].v] != vec[i].d) swap(vec[i].v, vec[i].d);
            }
    
            while(m--){
                scanf("%d%d%d", &a, &b, &c);
                if(a == 0){
                    modify(dfs_id[vec[b].v], c);
                }else{
                    printf("%d
    ",query_lct(b, c));
                }
            }
        }
    
        // system("pause");
        return 0;
    }
    
    /*
    附自制测试用例
    6 2
    1 2 2
    1 3 1
    2 4 3
    3 5 7
    3 6 5
    1 4 6
    1 4 6
    6 2
    1 2 2
    1 3 1
    2 4 3
    3 5 7
    3 6 5
    1 4 6
    1 4 6
    */
    
    ---- suffer now and live the rest of your life as a champion ----
  • 相关阅读:
    JavaScriptCore框架介绍
    可执行程序加载到内存的过程
    阿里云服务器怎么更换系统盘
    什么是A记录  域名
    宝塔服务器管理助手Linux面版-使用教程
    虚拟主机、VPS以及云主机的区别和对比
    怎样选择一个好的虚拟主机
    解Linux SSH命令大全,新手必看SSH命令
    虚拟主机,VPS,云主机之间的区别?
    云服务器和虚拟主机的区别:
  • 原文地址:https://www.cnblogs.com/popodynasty/p/14471422.html
Copyright © 2011-2022 走看看