Submission #1369660

#TimeUsernameProblemLanguageResultExecution timeMemory
1369660SpyrosAlivSprinkler (JOI22_sprinkler)C++20
3 / 100
2145 ms1050532 KiB
#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int MN = 2e5+1;
const int MD = 40;
const int LOG = 18;

class segTree {
    int n;
    ll mod;
    vector<ll> seg;
    void upd(int node, int start, int end, int idx, ll v) {
        if (start == end) {
            seg[node] = (v * seg[node]) % mod;
        }
        else {
            int mid = (start + end) / 2;
            if (idx <= mid) upd(node*2+1, start, mid, idx, v);
            else upd(node*2+2, mid+1, end, idx, v);
            seg[node] = (seg[node*2+1] * seg[node*2+2]) % mod;
        }
    }
    ll query(int node, int start, int end, int l, int r) {
        if (start > r || end < l) return 1;
        else if (start >= l && end <= r) return seg[node];
        else {
            int mid = (start + end) / 2;
            return (query(node*2+1, start, mid, l, r) * query(node*2+2, mid+1, end, l, r)) % mod;
        }
    }
    public:
    void inittt(int nn, ll lll) {
        n = nn;
        mod = lll;
        seg.assign(4*nn, 1);
    }
    void upd(int idx, ll v) {
        upd(0, 0, n, idx, v);
    }
    ll query(int l, int r) {
        l = max(0, l);
        r = min(r, n);
        if (l > r) return 1;
        return query(0, 0, n, l, r);
    }
};

int n, q;
ll l;
segTree segs[MN][MD];
vector<int> tree[MN];
vector<pair<int, int>> ancs[MN];
vector<int> centCh[MN];
int up[MN][LOG], dep[MN], tin[MN], tout[MN], t = 0;
ll h[MN];
int par[MN], sub[MN], chIdx[MN], root, centPar[MN];
bool ok[MN];

void prec(int node, int p = 0) {
    tin[node] = t++;
    up[node][0] = p;
    for (int i = 1; i < LOG; i++) {
        up[node][i] = up[up[node][i-1]][i-1];
    }
    for (auto next: tree[node]) {
        if (next == p) continue;
        dep[next] = dep[node] + 1;
        prec(next, node);
    }
    tout[node] = t++;
}

bool is_anc(int u, int v) {
    return tin[u] <= tin[v] && tout[u] >= tout[v]; 
}

int get_lca(int u, int v) {
    if (u == v) return u;
    if (dep[u] < dep[v]) swap(u, v);
    for (int i = LOG-1; i >= 0; i--) {
        if (!is_anc(up[u][i], v)) u = up[u][i];
    }
    return up[u][0];
}

int get_dis(int u, int v) {
    int lca = get_lca(u, v);
    return dep[u] + dep[v] - 2 * dep[lca];
}

void get_subs(int node, int p = 0) {
    if (ok[node]) return;
    sub[node] = 1;
    for (auto next: tree[node]) {
        if (next == p || ok[next]) continue;
        get_subs(next, node);
        sub[node] += sub[next];
    }
}

int get_centroid(int node, int sz, int prev = 0) {
    for (auto next: tree[node]) {
        if (ok[next] || next == prev) continue;
        if (sub[next] * 2 >= sz) return get_centroid(next, sz, node);
    }
    return node;
}

int build_centroid(int curr, int prev = 0) {
    get_subs(curr);
    int cent = get_centroid(curr, sub[curr]);
    ok[cent] = true;
    centCh[cent].push_back(cent);
    ancs[cent].push_back({cent, 0});
    for (auto [anc, foo]: ancs[prev]) {
        ancs[cent].push_back({anc, get_dis(anc, cent)});
    }
    if (prev != 0) {
        centCh[prev].push_back(cent);
        chIdx[cent] = centCh[prev].size() - 1;
    }
    for (auto next: tree[cent]) {
        if (ok[next]) continue;
        int nextCent = build_centroid(next, cent);
        centPar[nextCent] = cent;
    }
    return cent;
}

void update(int u, int maxDis, ll w) {
    int prev = 0;
    for (auto [anc, dis]: ancs[u]) {
        if (dis > maxDis) {
            prev = anc;
            continue;
        }
        int remDis = min(MD-2, maxDis - dis);
        for (int i = 0; i <= remDis; i++) {
            if (prev != 0) segs[anc][i].upd(chIdx[prev], w);
            else segs[anc][i].upd(0, w);
        }
        prev = anc;
    }
}

ll get_val(int u) {
    ll fin = h[u];
    int prev = -1;
    for (auto [anc, dis]: ancs[u]) {
        if (dis >= MD) {
            prev = anc;
            continue;
        }
        int split = -1;
        if (prev == -1) split = -1;
        else split = chIdx[prev];
        fin = fin * segs[anc][dis].query(0, split - 1) % l;
        fin = fin * segs[anc][dis].query(split+1, centCh[anc].size()-1) % l;
        prev = anc;
    }
    return fin;
}

void solve() {
    cin >> n >> l;
    for (int i = 1; i < n; i++) {
        int u, v; cin >> u >> v;
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    for (int i = 1; i <= n; i++) cin >> h[i];
    dep[1] = 0;
    tout[0] = 4*n;
    prec(1, 0);
    root = build_centroid(1);
    for (int i = 1; i <= n; i++) {
        for (int d = 0; d < MD; d++) {
            segs[i][d].inittt(centCh[i].size(), l);
        }
    }
    cin >> q;
    while (q--) {
        int t; cin >> t;
        if (t == 1) {
            int x, d;
            ll w; 
            cin >> x >> d >> w;
            update(x, d, w);
        }
        else {
            int x; cin >> x;
            ll ans = get_val(x);
            cout << ans << "\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    solve();
    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...