zoukankan      html  css  js  c++  java
  • P3384 【模板】轻重链剖分(树链剖分)

    树链剖分

    • (x->y)结点最短路径上所有节点的值都加上(z)
    • (x->y)结点最短路径上所有节点的值之和
    • (x)为根节点的子树内所有节点值都加上(z)
    • 求以(x)为根节点的子树内所有节点值和

    P3384 【模板】轻重链剖分

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define DOF 0x7f7f7f7f
    #define endl '
    '
    #define mem(a, b) memset(a, b, sizeof(a))
    #define debug(case, x) cout << case << "  : " << x << endl
    #define open freopen("ii.txt", "r", stdin)
    #define close freopen("oo.txt", "w", stdout)
    #define IO                       
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0)
    #define pb push_back
    using namespace std;
    //#define int long long
    #define lson rt << 1
    #define rson rt << 1 | 1
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef pair<long long, long long> PII;
    const int maxn = 2e5 + 10;
    
    int n, m, r, mod;
    
    int head[maxn], tot;
    struct edge {
        int to, next;
    } edge[maxn];
    
    int w[maxn], wt[maxn];
    //w输入时的权值,wt编号后的权值
    
    int son[maxn], id[maxn], fa[maxn], dep[maxn], sz[maxn], top[maxn], cnt = 0;
    //son重儿子、id新编号、fa父亲节点、dep深度、sz子树大小、top顶端、cnt标号。
    void add(int u, int v) {
        edge[++tot].to = v;
        edge[tot].next = head[u];
        head[u] = tot;
    }
    
    struct SegTree {
        int tree[maxn << 2], lazy[maxn << 2];
    
        void push_down(int rt, int len) {
            if(lazy[rt]) {
                lazy[lson] += lazy[rt];
                lazy[rson] += lazy[rt];
                tree[lson] += lazy[rt] * (len - len / 2);
                tree[rson] += lazy[rt] * (len / 2);
                tree[lson] %= mod;
                tree[rson] %= mod;
                lazy[rt] = 0;
            }
    
        }
    
        void build(int rt, int l, int r) {
            if(l == r) {
                tree[rt] = wt[l];
                tree[rt] %=  mod;
                return ;
            }
            int mid = (l + r) >> 1;
            build(lson, l, mid);
            build(rson, mid + 1, r);
    
            tree[rt] = (tree[lson] + tree[rson]) % mod;
        }
    
        int query(int rt, int l, int r, int L, int R) {
            if(L <= l && r <= R) {
                return tree[rt];
            }
            push_down(rt, r - l + 1);
            int mid = (l + r) >> 1, res = 0;
            if(L <= mid)
                res = (res + query(lson, l, mid, L, R)) % mod;
            if(R > mid)
                res = (res + query(rson, mid + 1, r, L, R)) % mod;
            return res;
    
        }
    
        void update(int rt, int l, int r, int L, int R, int k) {
            if(L <= l && r <= R) {
                lazy[rt] += k;
                tree[rt] += k * (r - l + 1);
                return ;
            }
            push_down(rt, r - l + 1);
            int mid = (l + r) >> 1;
    
            if(L <= mid)
                update(lson, l, mid, L, R, k);
            if(R > mid)
                update(rson, mid + 1, r, L, R, k);
    
            tree[rt] = (tree[lson] + tree[rson]) % mod;
        }
    } s_t;
    
    int query(int x, int y) {
        int res = 0;
        while(top[x] != top[y]) {
            if(dep[top[x]] < dep[top[y]])swap(x, y);
            res += s_t.query(1, 1, n, id[top[x]], id[x]);
            res %= mod;
            x = fa[top[x]];
        }
        if(dep[x] > dep[y])swap(x, y);
        res += s_t.query(1, 1, n, id[x], id[y]);
        res %= mod;
        return res;
    }
    
    void update(int x, int y, int k) {
        while(top[x] != top[y]) {
            if(dep[top[x]] < dep[top[y]])swap(x, y);
            s_t.update(1, 1, n, id[top[x]], id[x], k);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y])swap(x, y);
        s_t.update(1, 1, n, id[x], id[y], k);
    
    }
    
    int query_son(int x) {
        int res = 0;
        res += s_t.query(1, 1, n, id[x], id[x] + sz[x] - 1);
        res %= mod;
        return res;
    
    }
    
    void update_son(int x, int k) {
        s_t.update(1, 1, n, id[x], id[x] + sz[x] - 1, k);
    
    }
    
    
    void dfs1(int u, int father) {
        dep[u] = dep[father] + 1;
        sz[u] = 1;
        fa[u] = father;
        int maxson = -1;
        for(int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].to;
            if(v == father)continue;
            dfs1(v, u);
            sz[u] += sz[v];
            if(sz[v] > maxson)
                son[u] = v, maxson = sz[v];
        }
    
    }
    
    void dfs2(int u, int topf) {
        id[u] = ++cnt;
        wt[cnt] = w[u];
        top[u] = topf;
        if(!son[u]) return ;
        dfs2(son[u], topf);
        for(int i = head[u]; i; i = edge[i].next) {
            int v = edge[i].to;
            if(v == fa[u] || v == son[u]) continue;
            dfs2(v, v);
        }
    
    }
    
    
    int main() {
        scanf("%d%d%d%d", &n, &m, &r, &mod);
        for(int i = 1; i <= n; ++i)scanf("%d", &w[i]);
        for(int i = 1; i < n; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y);
            add(y, x);
        }
        dfs1(r, 0);
        dfs2(r, r);
        s_t.build(1, 1, n);
        while(m--) {
            int k, x, y, z;
            scanf("%d", &k);
            if(k == 1) {
                scanf("%d%d%d", &x, &y, &z);
                update(x, y, z);
            } else if(k == 2) {
                scanf("%d%d", &x, &y);
                printf("%d
    ", query(x, y));
            } else if(k == 3) {
                scanf("%d%d", &x, &y);
                update_son(x, y);
            } else {
                scanf("%d", &x);
                printf("%d
    ", query_son(x));
            }
        }
    
    
    }
    
  • 相关阅读:
    Chrony时间同步
    使用cfssl生成自签证书
    Docker运行时资源限制
    Docker的OverlayFS存储驱动
    Docker文件挂载总结
    Docker配置文件deamon.json详解
    Docker网络模式详解
    Dcoker命令使用详解
    Docker架构分解
    《数据采集和分析平台》笔记
  • 原文地址:https://www.cnblogs.com/waryan/p/13472010.html
Copyright © 2011-2022 走看看