zoukankan      html  css  js  c++  java
  • [hdu3966 Aragorn's Story]树链剖分

    题意:要求在一棵N(<=50000)个带权节点的树上支持3种操作

    (1)I u v w,u到v的路径上每个节点权值增加w

    (2)D u v w,u到v的路径上每个节点权值减少w

    (3)Q u,求u点的权值

    思路:

    将树剖分成若干条链,然后用区间数据结构来维护,这就是树链剖分。树链剖分后,这个题可以转化为一个“区间修改,单点查询”的问题,树状数组或线段树即可。

    树状数组(1100ms):

    #pragma comment(linker, "/STACK:10240000,10240000")
    
    #include <iostream>
    #include <cstdio>
    #include <ctime>
    #include <cstring>
    using namespace std;
    #define X first
    #define Y second
    #define pb(x) push_back(x)
    #define mp(x, y) make_pair(x, y)
    #define all(a) (a).begin(), (a).end()
    #define mset(a, x) memset(a, x, sizeof(a))
    #define mcpy(a, b) memcpy(a, b, sizeof(b))
    #define cas() int T, cas = 0; cin >> T; while (T --)
    template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
    template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
    typedef long long ll;
    typedef pair<int, int> pii;
    
    #ifndef ONLINE_JUDGE
        #include "local.h"
    #endif
    
    const int N = 5e4 + 7;
    const int M = N;
    
    namespace Edge {
        int last[N], to[M << 1], next[M << 1], cntE;
        void init() {
            cntE = 0;
            memset(last, -1, sizeof(last));
        }
        void addEdge(int u, int v) {
            to[cntE] = v;
            next[cntE] = last[u];
            last[u] = cntE ++;
        }
    }
    
    namespace TreeChain {
        int dep[N], top[N], w[N], son[N], siz[N], fa[N];
        int id[N], rnk[N], cntID;
        void init() {
            cntID = 0;
            memset(son, -1, sizeof(son));
        }
        void dfs1(int u, int f, int d) {
            dep[u] = d;
            fa[u] = f;
            siz[u] = 1;
            for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {
                int v = Edge::to[i];
                if (v != f) {
                    dfs1(v, u, d + 1);
                    siz[u] += siz[v];
                    if (son[u] == -1 || siz[v] > siz[son[u]])
                        son[u] = v;
                }
            }
        }
        void dfs2(int u, int t) {
            top[u] = t;
            id[u] = ++ cntID;
            rnk[id[u]] = u;
            if (son[u] == -1) return;
            dfs2(son[u], t);
            for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {
                int v = Edge::to[i];
                if (v != son[u] && v != fa[u])
                    dfs2(v, v);
            }
        }
    }
    
    int a[N];
    
    namespace TreeArray {
        int c[N], n;
        void init(int n) {
            memset(c, 0, sizeof(c));
            TreeArray::n = n;
        }
        int lowbit(int x) { return x & -x; }
        void add(int p, int x) {
            while (p <= n) {
                c[p] += x;
                p += lowbit(p);
            }
        }
        void add(int l, int r, int x) {
            add(l, x);
            add(r + 1, -x);
        }
        int query(int p) {
            int ans = 0;
            while (p) {
                ans += c[p];
                p -= lowbit(p);
            }
            return ans;
        }
        void change(int u, int v, int w) {
            using namespace TreeChain;
            while (top[u] != top[v]) {
                if (dep[top[u]] < dep[top[v]]) swap(u, v);
                add(id[top[u]], id[u], w);
                u = fa[top[u]];
            }
            if (dep[u] > dep[v]) swap(u, v);
            add(id[u], id[v], w);
        }
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n, m, p, u, v, w;
        char s[2];
        while (cin >> n >> m >> p) {
            Edge::init();
            TreeChain::init();
            for (int i = 1; i <= n; i ++) {
                scanf("%d", a + i);
            }
            for (int i = 0; i < m; i ++) {
                scanf("%d%d", &u, &v);
                Edge::addEdge(u, v);
                Edge::addEdge(v, u);
            }
            TreeChain::dfs1(1, 0, 0);
            TreeChain::dfs2(1, 1);
            TreeArray::init(n);
            for (int i = 1; i <= n; i ++) {
                TreeArray::add(i, i, a[TreeChain::rnk[i]]);
            }
            for (int i = 0; i < p; i ++) {
                scanf("%s", s);
                if (*s == 'Q') {
                    scanf("%d", &u);
                    printf("%d
    ", TreeArray::query(TreeChain::id[u]));
                }
                else {
                    scanf("%d%d%d", &u, &v, &w);
                    if (*s == 'D') w = -w;
                    TreeArray::change(u, v, w);
                }
            }
        }
        return 0;
    }
    

    线段树(1900ms):

    #pragma comment(linker, "/STACK:10240000,10240000")
    
    #include <iostream>
    #include <cstdio>
    #include <ctime>
    #include <cstring>
    using namespace std;
    #define X first
    #define Y second
    #define pb(x) push_back(x)
    #define mp(x, y) make_pair(x, y)
    #define all(a) (a).begin(), (a).end()
    #define mset(a, x) memset(a, x, sizeof(a))
    #define mcpy(a, b) memcpy(a, b, sizeof(b))
    #define cas() int T, cas = 0; cin >> T; while (T --)
    template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}
    template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}
    typedef long long ll;
    typedef pair<int, int> pii;
    
    #ifndef ONLINE_JUDGE
        #include "local.h"
    #endif
    
    const int N = 5e4 + 7;
    const int M = N;
    
    namespace Edge {
        int last[N], to[M << 1], next[M << 1], cntE;
        void init() {
            cntE = 0;
            memset(last, -1, sizeof(last));
        }
        void addEdge(int u, int v) {
            to[cntE] = v;
            next[cntE] = last[u];
            last[u] = cntE ++;
        }
    }
    
    namespace TreeChain {
        int dep[N], top[N], w[N], son[N], siz[N], fa[N];
        int id[N], rnk[N], cntID;
        void init() {
            cntID = 0;
            memset(son, -1, sizeof(son));
        }
        void dfs1(int u, int f, int d) {
            dep[u] = d;
            fa[u] = f;
            siz[u] = 1;
            for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {
                int v = Edge::to[i];
                if (v != f) {
                    dfs1(v, u, d + 1);
                    siz[u] += siz[v];
                    if (son[u] == -1 || siz[v] > siz[son[u]])
                        son[u] = v;
                }
            }
        }
        void dfs2(int u, int t) {
            top[u] = t;
            id[u] = ++ cntID;
            rnk[id[u]] = u;
            if (son[u] == -1) return;
            dfs2(son[u], t);
            for (int i = Edge::last[u]; ~i; i = Edge::next[i]) {
                int v = Edge::to[i];
                if (v != son[u] && v != fa[u])
                    dfs2(v, v);
            }
        }
    }
    
    int a[N];
    
    namespace SegTree {
        #define lson l, m, rt << 1
        #define rson m + 1, r, rt << 1 | 1
        int sum[N << 2], mark[N << 2];
        void up(int rt) {
            sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        }
        void down(int rt, int len) {
            int rlen = len >> 1, llen = len - rlen;
            if (mark[rt]) {
                sum[rt << 1] += llen * mark[rt];
                mark[rt << 1] += mark[rt];
                sum[rt << 1 | 1] += rlen * mark[rt];
                mark[rt << 1 | 1] += mark[rt];
                mark[rt] = 0;
            }
        }
        void build(int l, int r, int rt) {
            mark[rt] = 0;
            if (l == r) {
                sum[rt] = a[TreeChain::rnk[l]];
                return;
            }
            int m = (l + r) >> 1;
            build(lson);
            build(rson);
            up(rt);
        }
        void update(int L, int R, int x, int l, int r, int rt) {
            if (L <= l && r <= R) {
                sum[rt] += (r - l + 1) * x;
                mark[rt] += x;
                return;
            }
            int m = (l + r) >> 1;
            down(rt, r - l + 1);
            if (L <= m) update(L, R, x, lson);
            if (R > m) update(L, R, x, rson);
            up(rt);
        }
        int query(int p, int l, int r, int rt) {
            if (l == r) return sum[rt];
            int m = (l + r) >> 1;
            down(rt, r - l + 1);
            if (p <= m) return query(p, lson);
            else return query(p, rson);
        }
        void change(int u, int v, int w, int n) {
            using namespace TreeChain;
            while (top[u] != top[v]) {
                if (dep[top[u]] < dep[top[v]]) swap(u, v);
                update(id[top[u]], id[u], w, 1, n, 1);
                u = fa[top[u]];
            }
            if (dep[u] > dep[v]) swap(u, v);
            update(id[u], id[v], w, 1, n, 1);
        }
        #undef lson
        #undef rson
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n, m, p, u, v, w;
        char s[2];
        while (cin >> n >> m >> p) {
            Edge::init();
            TreeChain::init();
            for (int i = 1; i <= n; i ++) {
                scanf("%d", a + i);
            }
            for (int i = 0; i < m; i ++) {
                scanf("%d%d", &u, &v);
                Edge::addEdge(u, v);
                Edge::addEdge(v, u);
            }
            TreeChain::dfs1(1, 0, 0);
            TreeChain::dfs2(1, 1);
            SegTree::build(1, n, 1);
            for (int i = 0; i < p; i ++) {
                scanf("%s", s);
                if (*s == 'Q') {
                    scanf("%d", &u);
                    printf("%d
    ", SegTree::query(TreeChain::id[u], 1, n, 1));
                }
                else {
                    scanf("%d%d%d", &u, &v, &w);
                    if (*s == 'D') w = -w;
                    SegTree::change(u, v, w, n);
                }
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    汇编Ring 3下实现 HOOK API
    软件调试之INT 3讲解
    Delphi逆向
    XoftSpy 4.13的注册算法分析
    反调试技术揭秘
    jmp && call && ret 特权级转移 & 进程调度
    PHP Warning: Module 'modulename' already loaded in Unknown on line 0
    PhpStorm和PHPstudy配置调试参数(Xdebug),问题描述Error. Interpreter is not specified or invalid. Press “Fix” to edit your project configuration.
    php 安装xdebug进行调试(phpstorm)
    Windows下PHP多线程扩展pthreads的安装
  • 原文地址:https://www.cnblogs.com/jklongint/p/4950641.html
Copyright © 2011-2022 走看看