Untitled

 avatar
unknown
c_cpp
a year ago
5.2 kB
5
Indexable
#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define fi first
#define se second
#define pii pair<int, int>
#define pll pair<long long, long long>
using namespace std;
 
const int MAX = 3e5 + 5;
ll dp[MAX][20];
vector<int> edges[MAX];
vector<ll> tree(MAX * 4);
vector<ll> lazy(MAX * 4);
vector<ll> v(MAX);
vector<int> parent(MAX);
vector<int> level(MAX);
vector<int> subg(MAX);
vector<int> heavy(MAX);
vector<int> reorder(MAX);
vector<int> top_chain(MAX);
int cnt = 0;
 
void push(int idx, int left, int right) {
    if (lazy[idx] != 0) {
        tree[idx] = lazy[idx];
        if (left != right) {
            lazy[idx * 2] = lazy[idx];
            lazy[idx * 2 + 1] = lazy[idx];
        }
        lazy[idx] = 0;
    }
 
    return;
}
 
void update(int idx, int left, int right, int a, int b, ll val) {
    push(idx, left, right);
    if (left > b || right < a) return;
 
    if (left >= a && right <= b) {
        tree[idx] += (right - left + 1) * val;
        if (left != right) {
            lazy[idx * 2] += val;
            lazy[idx * 2 + 1] += val;
        }
        return;
    }
 
    int mid = (left + right) / 2;
    update(idx * 2, left, mid, a, b, val);
    update(idx * 2 + 1, mid + 1, right, a, b, val);
    tree[idx] = tree[idx * 2] + tree[idx * 2 + 1];
}
 
ll query(int idx, int left, int right, int a, int b) {
    push(idx, left, right);
    if (left > b || right < a) return 0;
    if (left >= a && right <= b) return tree[idx];
 
    int mid = (left + right) / 2;
    return query(idx * 2, left, mid, a, b) + query(idx * 2 + 1, mid + 1, right, a, b);
}
 
void dfs1(int a, int prev) {
    level[a] = level[prev] + 1;
    dp[a][0] = prev;
    for (int j = 1; j < 20; j++) {
        dp[a][j] = dp[dp[a][j - 1]][j - 1];
    }
 
    for (auto e : edges[a]) {
        if (e == prev) continue;
        dfs1(e, a);
    }
 
    return;
}
 
int lca(int a, int b) {
    if (level[a] < level[b]) swap(a, b);
    int diff = level[a] - level[b];
    for (int j = 0; j < 20; j++) {
        if (diff & 1 << j) a = dp[a][j];
    }
 
    if (a == b) return a;
    for (int j = 19; j >= 0; j--) {
        if (dp[a][j] == dp[b][j]) continue;
        a = dp[a][j];
        b = dp[b][j];
    }
 
    return dp[a][0];
}
 
void dfs2(int a, int prev) {
    parent[a] = prev;
    subg[a] = 1;
    for (auto e : edges[a]) {
        if (e == prev) continue;
        dfs2(e, a);
        subg[a] += subg[e];
        if (subg[e] > subg[heavy[a]]) heavy[a] = e;
    }
 
    return;
}
 
void dfs3(int a, int prev) {
    reorder[a] = ++cnt;
    if (heavy[a]) dfs3(heavy[a], a);
    for (auto e : edges[a]) {
        if (e == prev) continue;
        if (e == heavy[a]) continue;
        dfs3(e, a);
    }
 
    return;
}
 
void dfs4(int a, int prev) {
    for (auto e : edges[a]) {
        if (e == prev) continue;
        if (e == heavy[a]) top_chain[e] = top_chain[a];
        else top_chain[e] = e;
        dfs4(e, a);
    }
 
    return;
}
 
ll calc(int a, int c, int n) {
    ll ans = query(1, 0, n, reorder[a], reorder[a]);
    while(a != c) {
        if (top_chain[a] == a) {
            ans += query(1, 0, n, reorder[parent[a]], reorder[parent[a]]);
            a = parent[a];
        }
        else if (level[c] > level[top_chain[a]]){
            ans += query(1, 0, n, reorder[c], reorder[parent[a]]);
            a = c;
        }
        else {
            ans += query(1, 0, n, reorder[top_chain[a]], reorder[parent[a]]);
            a = top_chain[a];
        }
    }
 
    return ans;
}
 
void update_path(int a, int c, ll val, int n) {
    update(1, 0, n, reorder[a], reorder[a], val);
    while(a != c) {
        if (top_chain[a] == a) {
            update(1, 0, n, reorder[parent[a]], reorder[parent[a]], val);
            a = parent[a];
        }
        else if (level[c] > level[top_chain[a]]){
            update(1, 0, n, reorder[c], reorder[parent[a]], val);
            a = c;
        }
        else {
            update(1, 0, n, reorder[top_chain[a]], reorder[parent[a]], val);
            a = top_chain[a];
        }
    }
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n, q, a, b, t;
    ll x;
    cin >> n >> q;
    for (int i = 1; i <= n; i++) cin >> v[i];
    for (int i = 0; i < n - 1; i++) {
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }
 
        dfs1(1, 0);
        dfs2(1, 0);
        dfs3(1, 0);
        dfs4(1, 0);
 
    for (int i = 1; i <= n; i++) update(1, 0, n, reorder[i], reorder[i], v[i]);
 
    while(q--) {
        cin >> t;
        if (t == 1) {
            cin >> a >> b >> x;
            int c = lca(a, b);
            update_path(a, c, x, n);
            update_path(b, c, x, n);
            update_path(c, c, -x, n);
        }
        else {
            cin >> a >> b;
            int c = lca(a, b);
            ll ans = calc(a, c, n) + calc(b, c, n) - calc(c, c, n);
            cout << ans << "\n";
 
        }
    }
 
    return 0;
}
Editor is loading...
Leave a Comment