zoukankan      html  css  js  c++  java
  • P3384 [模板] 树链剖分

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, m, rt, mod, cnt, tot;
    int val[100005];
    int dep[100005];
    int id[100005], ed[100005];
    int rk[100005];
    int sz[100005];
    int fa[100005];
    int son[100005];
    int top[100005];
    ll sum[400005];
    ll lz[400005];
    
    struct node {
        int to, nex;
    }E[200005];
    int head[100005];
    
    void dfs1(int x, int pre, int d) {
        sz[x] = 1;
        dep[x] = d;
        fa[x] = pre;
        for(int i = head[x]; i; i = E[i].nex) {
            int v = E[i].to;
            if(v == pre) continue;
    
            dfs1(v, x, d + 1);
            sz[x] += sz[v];
            if(sz[son[x]] < sz[v]) son[x] = v;
        }
    }
    
    void dfs2(int x, int t) {
        top[x] = t;
        id[x] = ++tot;
        rk[tot] = x;
        if(!son[x]) {
            ed[x] = tot;
            return;
        }
    
        dfs2(son[x], t);
        for(int i = head[x]; i; i = E[i].nex) {
            int v = E[i].to;
            if(v == son[x] || v == fa[x]) continue;
            dfs2(v, v);
        }
        ed[x] = tot;
    }
    
    void pushup(int rt) {
        sum[rt] = (sum[rt << 1] + sum[rt << 1 | 1]) % mod;
    }
    
    void pushdown(int l, int r, int rt) {
        if(lz[rt]) {
            int m = l + r >> 1;
            sum[rt << 1] = (sum[rt << 1] + 1LL * (m - l + 1) * lz[rt] % mod) % mod;
            sum[rt << 1 | 1] = (sum[rt << 1 | 1] + 1LL * (r - m) * lz[rt] % mod) % mod;
            lz[rt << 1] = (lz[rt << 1] + lz[rt]) % mod;
            lz[rt << 1 | 1] = (lz[rt << 1 | 1] + lz[rt]) % mod;
            lz[rt] = 0;
        }
    }
    
    void build(int l, int r, int rt) {
        if(l == r) {
            sum[rt] = 1LL * val[rk[l]] % mod;
            return;
        }
    
        int m = l + r >> 1;
        build(l, m, rt << 1);
        build(m + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    
    void update(int ql, int qr, ll val, int l, int r, int rt) {
        if(ql <= l && qr >= r) {
            sum[rt] += 1LL * (r - l + 1) * val % mod;
            sum[rt] %= mod;
            lz[rt] += val;
            lz[rt] %= mod;
            return;
        }
    
        pushdown(l, r, rt);
        int m = l + r >> 1;
        if(ql <= m) update(ql, qr, val, l, m, rt << 1);
        if(qr > m) update(ql, qr, val, m + 1, r, rt << 1 | 1);
        pushup(rt);
    }
    
    ll query(int ql, int qr, int l, int r, int rt) {
        if(ql <= l && qr >= r) return sum[rt];
    
        pushdown(l, r, rt);
        ll res = 0;
    
        int m = l + r >> 1;
        if(ql <= m) res += query(ql, qr, l, m, rt << 1);
        if(qr > m) res += query(ql, qr, m + 1, r, rt << 1 | 1);
        res %= mod;
        return res;
    }
    
    ll cal_sum(int x, int y) {
        ll res = 0;
        int fx = top[x];
        int fy = top[y];
        while(fx != fy) {
            if(dep[fx] >= dep[fy]) {
                res += query(id[fx], id[x], 1, n, 1);
                res %= mod;
                x = fa[fx]; fx = top[x];
            } else {
                res += query(id[fy], id[y], 1, n, 1);
                res %= mod;
                y = fa[fy]; fy = top[y];
            }
        }
        if(id[x] <= id[y]) res += query(id[x], id[y], 1, n, 1);
        else res += query(id[y], id[x], 1, n, 1);
        res %= mod;
    
        return res;
    }
    
    void update_lian(int x, int y, ll val) {
        int fx = top[x];
        int fy = top[y];
        while(fx != fy) {
            if(dep[fx] >= dep[fy]) {
                update(id[fx], id[x], val, 1, n, 1);
                x = fa[fx]; fx = top[x];
            } else {
                update(id[fy], id[y], val, 1, n, 1);
                y = fa[fy]; fy = top[y];
            }
        }
        if(id[x] <= id[y]) update(id[x], id[y], val, 1, n, 1);
        else update(id[y], id[x], val, 1, n, 1);
    }
    
    int main() {
        scanf("%d%d%d%d", &n, &m, &rt, &mod);
        cnt = 0;
        tot = 0;
        for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
        for(int i = 1; i < n; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt;
            E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt;
        }
        dfs1(rt, 0, 1);
        dfs2(rt, rt);
        build(1, n, 1);
        while(m--) {
            int opt;
            scanf("%d", &opt);
    
            int a, b, c;
            if(opt == 1) {
                scanf("%d%d%d", &a, &b, &c);
                c %= mod;
                update_lian(a, b, 1LL * c);
            } else if(opt == 2) {
                scanf("%d%d", &a, &b);
                printf("%lld
    ", cal_sum(a, b));
            } else if(opt == 3) {
                scanf("%d%d", &a, &b);
                b %= mod;
                update(id[a], ed[a], 1LL * b, 1, n, 1);
            } else {
                scanf("%d", &a);
                printf("%lld
    ", query(id[a], ed[a], 1, n, 1));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    多网卡绑定
    deepin 20.2.3 数字时钟屏保
    (原创)odoo15(master)下,列表导出权限控制
    在CentOS7上扩容centos-root根目录
    Linux扩容-新增磁盘分区挂载-fdisk
    Docker
    隐私政策(URL)
    快排代码
    反射将对象所有属性(含集合中所有属性)中字符串类型做trim()
    Prometheus 查询语句
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11141452.html
Copyright © 2011-2022 走看看