zoukankan      html  css  js  c++  java
  • HDU3966-Aragorn's Story(树链剖分)

    第一道树链剖分。

    早就想学。。一直懒。。

    感觉还是比较简单的。

    主要是要套其他数据结构,线段树大概还好,平衡树之类的肯定就跪了。

    http://blog.csdn.net/acdreamers/article/details/10591443 这篇博客写的真的超级棒 简单明了

    感觉树链剖分的难点就是更新的地方

    看懂之后自己写一遍错误也都在那里>_<

    树链剖分就是把数分成一个个链,然后首尾相连

    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int N = 50005;
    
    //
    struct Edge {
        int to, next;
    } edge[N*2];
    int head[N], cntE;
    void addedge(int u, int v) {
        edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
        edge[cntE].to = u; edge[cntE].next = head[v]; head[v] = cntE++;
    }
    //
    int dep[N], sz[N], fa[N], son[N];
    void dfs1(int u, int par, int d) {
        dep[u] = d; sz[u] = 1; fa[u] = par;
        for (int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].to;
            if (v != par) {
                dfs1(v, u, d+1);
                sz[u] += sz[v];
                if (son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v;
            }
        }
    }
    int top[N], dfn[N], rk[N], idx;
    void dfs2(int u, int rt) {
        top[u] = rt; dfn[u] = ++idx; rk[idx] = u;
        if (son[u] == -1) return;
        dfs2(son[u], rt);
        for (int i = head[u]; ~i; i = edge[i].next) {
            int v = edge[i].to;
            if (v != fa[u] && v != son[u]) dfs2(v, v);
        }
    }
    //
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    int sum[N<<2], a[N];
    void build(int o, int l, int r) {
        if (l == r) { sum[o] = a[rk[l]]; return; }
        int mid = (l+r) >> 1;
        build(lson); build(rson);
        sum[o] = 0;
    }
    
    void pushdown(int o) {
        if (sum[o]) {
            sum[o<<1] += sum[o];
            sum[o<<1|1] += sum[o];
            sum[o] = 0;
        }
    }
    
    int query(int o, int l, int r, int v) {
        if (l == r) return sum[o];
        pushdown(o);
        int mid = (l+r) >> 1;
        if (v <= mid) return query(lson, v);
        return query(rson, v);
    }
    
    void update(int o, int l, int r, int L, int R, int v) {
        if (l >= L && r <= R) { sum[o] += v; return ; }
        pushdown(o);
        int mid = (l+r) >> 1;
        if (L <= mid) update(lson, L, R, v);
        if (R > mid) update(rson, L, R, v);
    }
    
    void change(int x, int y, int w, int n) {
        while (top[x] != top[y]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            update(1, 1, n, dfn[top[x]], dfn[x], w);
            x = fa[top[x]];
        }
        if (dep[x] > dep[y]) swap(x, y);
        update(1, 1, n, dfn[x], dfn[y], w);
    }
    
    void init() {
        idx = cntE = 0;
        memset(head, -1, sizeof head);
        memset(son, -1, sizeof son);
    }
    
    int main()
    {
        int n, m, p;
        while (~scanf("%d%d%d", &n, &m, &p)) {
            init();
            int u, v, w;
            char op[2];
            for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
            for (int i = 1; i <= m; ++i) scanf("%d%d", &u, &v), addedge(u, v);
    
            dfs1(1, 0, 0); dfs2(1, 1); build(1, 1, n);
    
            while (p--) {
                scanf("%s", op);
                if (*op == 'Q') {
                    scanf("%d", &u);
                    printf("%d
    ", query(1, 1, n, dfn[u]));
                } else {
                    scanf("%d%d%d", &u, &v, &w);
                    if (*op == 'D') w = -w;
                    change(u, v, w, n);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    git使用
    javascript关于事件与闭包
    Ajax和跨域
    通过触发器进行的操作
    30分钟学会jquery插件
    那些年用过的jquery插件
    网页设计常用网页技巧
    XML操作
    效果A:浏览器跳转以及判断来路客户信息
    数据库
  • 原文地址:https://www.cnblogs.com/wenruo/p/5897689.html
Copyright © 2011-2022 走看看