树链剖分

树链剖分(未调程序)

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e6 + 10;
int read() {
    int k = 0, f = 1, c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for (; isdigit(c); c = getchar()) k = k * 10 + (c ^ 48);
    return k * f;
}
struct Edge {
    int to, next;
}edge[N];
int n, m, r, mod, idx, tot;
int w[N], wt[N], fa[N], head[N], dep[N], siz[N], hson[N], id[N], top[N];
void add (int u, int v) {
    edge[idx].to = v;
    edge[idx].next = head[u];
    head[u] = idx++; 
}


// ----------------------------------线段树部分-------------------------------------------------------------


struct node {
    int data, left, right, lazy;
}a[N];
void push_down (int Root) {
    a[Root * 2].data += a[Root * 2].lazy * (a[Root * 2].right - a[Root * 2].left + 1);
    a[Root * 2].lazy += a[Root].lazy;
    a[Root * 2 + 1].data += a[Root * 2 + 1].lazy * (a[Root * 2 + 1].right - a[Root * 2 + 1].left + 1);
    a[Root * 2 + 1].lazy += a[Root].lazy;
    a[Root * 2].data %= mod;
    a[Root * 2 + 1].data %= mod;
    a[Root].lazy = 0;
}
void build (int Root, int Left, int Right) {
    a[Root].left = Left;a[Root].right = Right;
    if (a[Root].left == a[Root].right) {
        int temp = wt[Left];
        a[Root].data = temp > mod ? temp % mod : temp;
        return ;
    }
    int mid = (Left + Right) >> 1;
    build (Root, Left, mid);
    build (Root, mid + 1, Right);
}
void modify (int Root, int Left, int Right, int k) {
    if (Left <= a[Root].left && Right >= a[Root].right) {
        a[Root].lazy += k;
        a[Root].data += (a[Root].right - a[Root].left + 1) * k;
        return;
    }
    push_down(Root);
    if (a[Root * 2].right >= Left) modify(Root* 2, Left, Right, k);
    if (a[Root * 2 + 1].left <= Right) modify(Root * 2 + 1, Left, Right, k);
    a[Root].data = a[Root * 2].data + a[Root * 2 + 1].data;
}
int query (int Root, int Left, int Right) {
	if (a[Root].right <= Right && a[Root].left >= Left) return a[Root].data;
	push_down(Root);
	int ans = 0;
	if (a[Root * 2].right >= Left) ans += query (Root * 2, Left, Right);
	if (a[Root * 2 + 1].left <= Right) ans += query (Root * 2 + 1, Left, Right);
	return ans;
}
// -----------------------------------树链剖分部分---------------------------------------------------------------


int rs;
void dfs1(int u, int father, int deepth) {
    dep[u] = dep[father] + 1;
    fa[u] = father;
    siz[u] = 1;
    int maxson = -1;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if (v == father) continue;
        dfs1 (v, u, deepth + 1);
        siz[u] = siz[v] + 1;
        if (siz[v] > maxson) {
            hson[u] = v;
            maxson = siz[v];
        }
    }
}
void dfs2 (int u, int father) {
    id[u] = ++tot;
    wt[u] = w[u];
    top[u] = father;
    dfs2 (hson[u], u);
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].to;
        if (v == father || v == hson[u]) continue;
        dfs2 (v, v);
    }
}
int qRange (int x, int y) {
    int ans = 0;
    while (top[x] != top[y]){ 
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        rs = 0;
        query(1, id[top[x]], id[x]);
        ans += rs;
        ans %= mod; 
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    rs = 0;
    query (1, id[x], id[y]);
    ans += rs;
    return ans % mod;
}
void updRange(int x, int y, int z) {
    z %= mod;
    while (top[x] != top[y]) {
        if (dep[x] > dep[y]) swap(x, y);
        modify(1, id[top[x]], id[x], z);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    modify(1, id[x], id[y], z);
}
int qson(int x){
    rs=0;
    query(1,id[x],id[x]+siz[x]-1);
    return rs;
}
void updson(int x,int k){
    modify(1,id[x],id[x]+siz[x]-1,k);
}
//---------------------------------------------------------------------------------------------------



int main() {
    memset(head, -1, sizeof(head));
    n = read(); m = read(); r = read(); mod = read();
    for (int i = 1; i <= n; i++) cin >> w[i];
    for (int i = 1; i < n; i++) {
        int x = read(), y = read();
        add (x, y);
        add (y, x);
    }
    dfs1 (r, 0, 1);
    dfs2 (r, r);
    build (1, 1, n);
    while (m --) {
        int opt = read();
        if (opt == 1) {
            int x = read(), y = read(), z = read();
            updRange(x, y, z);
        }
        else if (opt == 2) {
            int x = read(), y = read();
            cout << qRange(x, y) << '\n';
        }
        else if (opt == 3) {
            int x = read(), y = read();
            updson(x, y);
        }
        else {
            int x = read();
            cout << qson(x) << '\n';
        }
    }
    return 0;
}
posted @ 2026-05-29 22:50  mcGrindelwald  阅读(10)  评论(0)    收藏  举报