【模板】树链剖分

#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long LL;

const int M = 100005;
const int N = 100005;
int n, m, root, opt, x, y, u, v;
LL a[N], z, MOD;

struct Edge{
    int nxt, to;
}edge[M<<1];
int head[N], edge_num;
void add_edge(int from, int to){
    edge[++edge_num].nxt = head[from];
    edge[edge_num].to = to;
    head[from] = edge_num;
}

int fa[N], dep[N], sz[N], son[N];
void dfs(int x, int f, int depth){
    fa[x] = f, dep[x] = depth, sz[x] = 1, son[x] = 0;
    for(int i = head[x]; i; i = edge[i].nxt){
        if(edge[i].to == f) continue;
        dfs(edge[i].to, x, depth+1);
        sz[x] += sz[edge[i].to];
        if(!son[x] || sz[edge[i].to] > sz[son[x]])  son[x] = edge[i].to;
    }
}
int belong[N], start[N], end[N], dfs_clock, func[N];
void dfs(int x, int top){
    start[x] = ++dfs_clock, func[dfs_clock] = x;
    belong[x] = top;
    if(son[x])  dfs(son[x], top);
    for(int i = head[x]; i; i = edge[i].nxt){
        if(edge[i].to == son[x] || edge[i].to == fa[x]) continue;
        dfs(edge[i].to, edge[i].to);
    }
    end[x] = dfs_clock;
}

#define lid id<<1
#define rid id<<1|1
#define mid ((tr[id].l+tr[id].r)>>1)
#define len(id) (tr[id].r - tr[id].l + 1)

struct seg_tree{
    int l, r;
    LL lazy, sum;
}tr[N<<2];

void pushup(int id){
    tr[id].sum = tr[lid].sum + tr[rid].sum;
}

void pushdown(int id){
    if(tr[id].l != tr[id].r && tr[id].lazy != 0){
        LL t = tr[id].lazy;
        (tr[lid].lazy += t) %= MOD;
        (tr[lid].sum += len(lid) * t) %= MOD;
        (tr[rid].lazy += t) %= MOD;
        (tr[rid].sum += len(rid) * t) %= MOD;
        tr[id].lazy = 0;
    }
}

void build(int id, int l, int r){
    tr[id].l = l, tr[id].r = r;
    tr[id].lazy = 0;
    if(tr[id].l == tr[id].r){
        tr[id].sum = a[func[l]] % MOD;
        return;
    }
    build(lid, l, mid);
    build(rid, mid+1, r);
    pushup(id);
}

void add(int id, int l, int r, LL val){
    pushdown(id);
    if(tr[id].l == l && tr[id].r == r){
        (tr[id].lazy += val) %= MOD;
        (tr[id].sum += len(id) * val) %= MOD;
        return;
    }
    if(r <= mid)    add(lid, l, r, val);
    else if(l > mid)    add(rid, l, r, val);
    else    add(lid, l, mid, val), add(rid, mid+1, r, val);
    pushup(id);
}

LL query(int id, int l, int r){
    pushdown(id);
    if(tr[id].l == l && tr[id].r == r)
        return tr[id].sum % MOD;
    if(r <= mid)    return query(lid, l, r);
    else if(l > mid)    return query(rid, l, r);
    else    return (query(lid, l, mid) + query(rid, mid+1, r)) % MOD;
}

void Add_link(int u, int v, LL val){
    while(belong[u] != belong[v]){
        if(dep[belong[u]] < dep[belong[v]]) swap(u, v);
        add(1, start[belong[u]], start[u], val);
        u = fa[belong[u]];
    }
    if(dep[u] < dep[v]) swap(u, v);
    add(1, start[v], start[u], val);
}
LL Query_link(int u, int v){
    LL res = 0;
    while(belong[u] != belong[v]){
        if(dep[belong[u]] < dep[belong[v]]) swap(u, v);
        (res += query(1, start[belong[u]], start[u])) %= MOD;
        u = fa[belong[u]];
    }
    if(dep[u] < dep[v]) swap(u, v);
    (res += query(1, start[v], start[u])) %= MOD;
    return (res + MOD) % MOD;
}
void Add_sub(int u, LL val){
    add(1, start[u], end[u], val);
}
LL Query_sub(int u){
    return query(1, start[u], end[u]);
}

int main(){
    scanf("%d%d%d%lld", &n, &m, &root, &MOD);
    for(int i = 1; i <= n; i++)    scanf("%lld", &a[i]);
    for(int i = 1; i < n; i++){
        scanf("%d%d", &u, &v);
        add_edge(u, v);
        add_edge(v, u);
    }
    dfs(root, 0, 1);
    dfs(root, root);
    build(1, 1, n);
    while(m--){
        scanf("%d", &opt);
        if(opt == 1){
            scanf("%d%d%lld", &x, &y, &z);
            Add_link(x, y, z);
        }
        else if(opt == 2){
            scanf("%d%d", &x, &y);
            printf("%lld\n", Query_link(x, y));
        }
        else if(opt == 3){
            scanf("%d%lld", &x, &z);
            Add_sub(x, z);
        }
        else if(opt == 4){
            scanf("%d", &x);
            printf("%lld\n", Query_sub(x));
        }
    }
    return 0;
}

0 条评论

目前还没有评论...