zoukankan      html  css  js  c++  java
  • POJ 2763 LCA+BIT

    显然这个题是个好题, 
    需要修改边利用,前缀和思想动态维护, 每次查询u到v的距离
    记下每个点(u)第一次在dfs出现及最后回来的位置, strart和finish
    那么u连向其父亲的边在被修改是影响的只是start【u】和finish【u】之间的范围前缀和恰好可以运用, 还有就是要做一个点到边映射数组, 其实很简单。。哦对了, 相信BIT–树状数组这么6的东西大家都懂吧。。
    代码虽然长了, 但思路是很清晰的, 分了两个结构体来做

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define N 400010
    #define map Map
    #define next Next
    #define begin Begin
    #define C c = getchar()
    #define mem(a, b) memset(a, b, sizeof(a))
    #define rep(i, s, t) for(int i = s, end = t; i <= end; ++i)
    #define erep(i, u) for(int i = begin[u]; i != -1; i = next[i])
    
    bool vis[N];
    int eid[N], map[N], dis[N], start[N], finish[N];
    int e, cnt, tot, res, st, n, q;
    int to[N], next[N], begin[N];
    int dep[N], sum[N], dp[N][30], first[N], id[N], dist[N];
    
    void read(int &x) {
        char C; x = 0; while(c<'0' || c>'9') C;
        while(c >= '0' && c <= '9') x = x*10 + c-'0', C;
    }
    
    struct BIT {
        int tree[N];
        int lowbit(int x) {
            return x & -x;
        }
    
        void update(int i, int x) {
            while(i <= n) {
                tree[i] += x;
                i += lowbit(i);
            }
        }
    
        int sum(int end) {
            int ans = 0;
            while(end > 0) {
                ans += tree[end];
                end -= lowbit(end);
            }
            return ans;
        }
    }U;
    
    struct sparse_table {
        void add(int u, int v, int i) {
            eid[++e] = i;
            to[e] = v;
            next[e] = begin[u];
            begin[u] = e;
        }
    
        void dfs(int u, int depth) {
            int v;
            id[++tot] = u; vis[u] = true;
            first[u] = tot; dep[tot] = depth;
            start[u] = ++cnt;
            erep(i, u)
                if(!vis[v = to[i]]) {
                    map[eid[i]] = v;
                    dfs(v, depth + 1);
                    id[++tot] = u; dep[tot] = depth;
                }
            finish[u] = cnt;
        }
    
        void ST(int m) {
            rep(i, 1, m) dp[i][0] = i;
    
            for(int j = 1; (1<<j) <= m; ++j)
                for(int i = 1; i + (1<<j) - 1 <= m; ++i) {
                    int a = dp[i][j-1], b = dp[i+(1<<(j-1))][j-1];
                    dp[i][j] = dep[a] < dep[b]? a : b;
                }
        }
    
        int query(int l, int r) {
            int k = 0;
            while(1<<(k+1) <= r - l + 1) k++;
            int x = dp[l][k], y = dp[r - (1<<k) + 1][k];
            return dep[x] < dep[y]? x : y;
        }
    
        int LCA(int u, int v) {
            int x = first[u], y = first[v];
            if(x > y) swap(x, y);
            return id[query(x, y)];
        }
    }T;
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.in", "r", stdin);
        freopen("result.out", "w", stdout);
    #endif
        mem(begin, -1);
        scanf("%d%d%d", &n, &q, &st);
        rep(i, 1, n-1) {
            int u, v, w;
    //      scanf("%d%d%d", &u, &v, &w);
            read(u); read(v); read(w);
            dis[i] = w;
            T.add(u, v, i);
            T.add(v, u, i);
        }
    
        T.dfs(1, 1);
        T.ST(tot);
        rep(i, 1, n-1) 
            U.update(start[map[i]], dis[i]), U.update(finish[map[i]]+1, -dis[i]);
        rep(i, 1, q) {
            int t, u, w, xx;
    //      scanf("%d", &t);
            read(t);
            if(!t) {
    //          scanf("%d", &xx);
                read(xx);
                int lca = T.LCA(st, xx);
                printf("%d
    ", U.sum(start[st]) + U.sum(start[xx]) - (U.sum(start[lca])<<1));
                st = xx;
            }
            else {
        //      scanf("%d%d", &u, &w);
                read(u); read(w);
                U.update(start[map[u]], w - dis[u]);
                U.update(finish[map[u]]+1, dis[u] - w);
                dis[u] = w;
            }
        }
        return 0;
    }
    

    好了, LCA的blog就告一段落了, 以后有好题再发

  • 相关阅读:
    5G名词术语
    什么是IPv6
    如何用SecureCRT 登录eNSP模拟器里的设备
    numpy-排序
    numpy-tile 数组复制
    经纬度计算距离与方位角
    numpy-添加操作大全
    高效编程之 concurrent.future
    linux命令 集合
    PostgreSQL-表空间
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530166.html
Copyright © 2011-2022 走看看