求问,为什么我的程序会MLE?

P3384 【模板】重链剖分/树链剖分

GY程袁浩 @ 2024-07-22 15:04:27

//简单一点点了......
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
struct node {
    int l, r, sum, lz;
    #define l(x) tr[x].l
    #define r(x) tr[x].r
    #define sum(x) tr[x].sum
    #define lz(x) tr[x].lz
}tr[N * 4];
int n, m, r, p;
int h[N], e[N], ne[N], w[N], wt[N], idx;
int son[N], id[N], fa[N], tsize[N], dep[N], top[N], cnt;//线段树上请用id
void add(int a, int b) {
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}
void pushup(int x) { sum(x) = (sum(x * 2) + sum(x * 2 + 1)) % p; }
void build(int x, int l, int r) {
    l(x) = l, r(x) = r;
    if (l == r) {
        sum(x) = wt[l] % p;
        return;
    }
    int mid = l + r >> 1;
    build(x * 2, l, mid), build(x * 2 + 1, mid + 1, r);
    pushup(x);
}
void pushdown(int x) {
    (lz(x * 2) += lz(x)) %= p;
    (lz(x * 2 + 1) += lz(x)) %= p;
    (sum(x * 2) += lz(x) * ((r(x * 2) - l(x * 2) + 1) % p) % p) %= p;
    (sum(x * 2 + 1) += lz(x) * ((r(x * 2 + 1) - l(x * 2 + 1) + 1) % p) % p) %= p;
    lz(x) = 0;
}
void change(int x, int ll, int rr, int k) {
    int l = l(x), r = r(x);
    if (l >= ll && r <= rr) {
        (sum(x) += (r - l + 1) % p * (k % p) % p) %= p;
        lz(x) += k;
        return;
    }
    pushdown(x);
    int mid = l + r >> 1;
    if (ll <= mid) change(x * 2, ll, rr, k);
    if (rr > mid) change(x * 2 + 1, ll, rr, k);
    pushup(x);
}
int qry(int x, int ll, int rr) {
    int l = l(x), r = r(x);
    if (l >= ll && r <= rr) return sum(x);
    pushdown(x);
    int mid = l + r >> 1, sum = 0;
    if (ll <= mid) sum += qry(x * 2, ll, rr);
    if (rr > mid) sum += qry(x * 2 + 1, ll, rr);
    pushup(x);
    return sum;
}
//板子,很快的线段树板子
int qryrange(int x, int y) {
    int ans = 0;
    while (top[x] != top[y]) {//不在同链
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        (ans += qry(1, id[top[x]], id[x]) % p) %= p;//上升!
        x = fa[top[x]];
    }//O(log n) 类似lca???
    if (dep[x] > dep[y]) swap(x, y);//注意从小到大
    return (ans+qry(1,id[x],id[y])%p)%p;
}
void updrange(int x, int y, int z) {
    z %= p;
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        change(1, id[top[x]], id[x], z);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    change(1, id[x], id[y], z);
}
void updson(int x, int y) { change(1, id[x], id[x] + tsize[x] - 1, y); }
int qryson(int x) { return qry(1, id[x], id[x] + tsize[x] - 1); }
void dfs1(int x, int f, int deep) {
    dep[x] = deep;fa[x] = f;tsize[x] = 1;int maxn = -1;
    for (int i = h[x]; i != -1; i = ne[i]) {
        int j = e[i];
        if (j == f) continue;
        dfs1(j, x, deep + 1);
        tsize[x] += tsize[j];
        if (tsize[j] > maxn) maxn = tsize[j],son[x] = j;
    }
}
void dfs2(int x, int topf) {
    id[x] = ++cnt;wt[id[x]] = w[x];top[x] = topf;
    if (!son[x]) return;
    dfs2(son[x], topf);
    for (int i = h[x]; i != -1; i = ne[i]) {
        int j = e[i];
        if (j == fa[x] || j == son[x]) continue;
        dfs2(j, j);//新的链
    }
}
signed main() {
    memset(h, -1, sizeof h);cin >> n >> m >> r >> p;
    for (int i = 1; i <= n; i++) cin >> w[i];
    for (int i = 1; i <= n - 1; i++) {
        int x, y;cin >> x >> y;
        add(x, y), add(y, x);
    }
    dfs1(r, 0, 1);dfs2(r, r);build(1, 1, n);//剖分+建树
    for (int i = 1; i <= m; i++) {
        int c, x, y, z;
        cin >> c;
        if (c == 1) {
            cin >> x >> y >> z;
            updrange(x, y, z);
        }
        else if(c == 2) {
            cin >> x >> y;
            cout << qryrange(x, y) << endl;
        }
        else if (c == 3) {
            cin >> x >> y;
            updson(x, y);
        }
        else {
            cin >> x;
            cout << qryson(x) << endl;
        }
    }
    return 0;
}

by GY程袁浩 @ 2024-07-22 15:07:50

数组开小了


|