可能犯了一个很低级的错误,但是没查出来

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

Piggy343288 @ 2023-03-11 14:32:05

#include <bits/stdc++.h>
using namespace std;
namespace SegmentTree {
#define int long long
#define ls ((p) << 1)
#define rs ((p) << 1 | 1)
#define mid ((l) + (((r) - (l)) >> 1))
#define pdown pushdown(p, l, r)
#define pup pushup(p)
struct STree {
    static const int maxN = 1e5 + 10;
    int a[maxN], ans[maxN << 2], tag[maxN << 2];
    int n;
    void pushup(int p) { ans[p] = ans[ls] + ans[rs]; }
    void lazy_update(int p, int l, int r, int tg) {
        tag[p] += tg;
        ans[p] += (r - l + 1) * tg;
    }
    void pushdown(int p, int l, int r) {
        lazy_update(ls, l, mid, tag[p]);
        lazy_update(rs, mid + 1, r, tag[p]);
        tag[p] = 0;
    }
    void buildTree(int p, int l, int r) {
        tag[p] = 0;
        if (l == r) {
            ans[p] = a[l];
            return;
        }
        buildTree(ls, l, mid);
        buildTree(rs, mid + 1, r);
        pup;
    }
    int nl, nr, k;
    void update(int p, int l, int r) {
        // decleared nl,nr,k outside of the function and inside the struct.
        if (nl <= l && r <= nr) {
            lazy_update(p, l, r, k);
            return;
        }
        pdown;
        if (nl <= mid)
            update(ls, l, mid);
        if (nr > mid)
            update(rs, mid + 1, r);
        pup;
    }
    int query(int p, int l, int r) {
        // decleared nl,nr outside of the function and inside the struct.
        if (nl <= l && r <= nr) {
            return ans[p];
        }
        int ans = 0;
        pdown;
        if (nl <= mid)
            ans += query(ls, l, mid);
        if (nr > mid)
            ans += query(rs, mid + 1, r);
        pup;
        return ans;
    }
    void easy_update(int l, int r, int val) {
        nl = l, nr = r;
        k = val;
        update(1, 1, n);
    }
    int easy_query(int l, int r) {
        nl = l, nr = r;
        return query(1, 1, n);
    }
};
};  // namespace SegmentTree

namespace TreeDecomposition {
struct TreeDecom {
    int n;
    static const int maxN = 1e5 + 10;
    vector<int> edges[maxN];
    int father[maxN], top[maxN], dfn[maxN], size[maxN], hson[maxN], depth[maxN];
    SegmentTree::STree tree;

    int DFSh(int u, int fa, int level) {
        // Depth,Father,Search,hson
        depth[u] = level;
        father[u] = fa;
        int sizeU = 1;
        for (int i : edges[u]) {
            if (i == fa)
                continue;
            int sizeSon = DFSh(i, u, level + 1);
            if (sizeSon > size[hson[u]])
                hson[u] = i;
            sizeU += sizeSon;
        }
        return sizeU;
    }

    int cnt = 0;
    void Decomposition(int u, int topp) {
        top[u] = topp;
        cnt++;
        dfn[u] = cnt;
        if (hson[u]) {
            Decomposition(hson[u], topp);
            for (int i : edges[u]) {
                if (i != hson[u] && !dfn[i])
                    Decomposition(i, i);
            }
        }
    }
    int weights[maxN];
    int weightsNew[maxN];
    void replaceWeight() {
        for (int i = 1; i <= n; i++) {
            weightsNew[dfn[i]] = weights[i];
        }
        for (int i = 1; i <= n; i++) {
            weights[i] = weightsNew[i];
        }
    }
    void buildTree(int weights[], int l, int r) {
        for (int i = l; i <= r; i++) {
            tree.a[i - l + 1] = weights[i];
        }
        tree.buildTree(1, 1, r - l + 1);
    }
    void init() {
        DFSh(1, -1, 1);
        Decomposition(1, 1);
        replaceWeight();
        buildTree(weights, 1, n);
    }
    int query(int l, int r, int mod) {
        int ans = 0;
        while (top[l] != top[r]) {
            if (depth[top[l]] < depth[top[r]])
                swap(l, r);
            ans = (ans + tree.easy_query(dfn[top[l]], dfn[l]));
            l = father[top[l]];
        }
        if (depth[l] > depth[r])
            swap(l, r);
        ans = (ans + tree.easy_query(dfn[l], dfn[r])) % mod;
        return ans;
    }
    int querySubtree(int x) { return tree.easy_query(x, x + size[x] - 1); }
    void update(int l, int r, int k) {
        while (top[l] != top[r]) {
            if (depth[top[l]] < depth[top[r]])
                swap(l, r);
            tree.easy_update(dfn[top[l]], dfn[l], k);
            l = father[top[l]];
        }
        if (depth[l] > depth[r])
            swap(l, r);
        tree.easy_update(dfn[l], dfn[r], k);
    }
    void updateSubtree(int x, int k) {
        tree.easy_update(x, x + size[x] - 1, k);
    }
};
};  // namespace TreeDecomposition
TreeDecomposition::TreeDecom TD;

signed main1() {
    int n, m, r, p;
    cin >> n >> m >> r >> p;
    for (int i = 1; i <= n; i++)cin >> TD.weights[i];
    cout<<"Successfully read in weights.\n";
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        TD.edges[u].push_back(v);
        TD.edges[v].push_back(u);
        cout<<"Read "<<u<<" "<<v<<".\n";
    }
    cout<<"Successfully read in edges.\n";
    TD.init();
    while (m-- > 0) {
        int opt, x, y, z;
        cin >> opt;
        if (opt == 1) {
            cin >> x >> y >> z;
            TD.update(x, y, z);
        } else if (opt == 2) {
            cin >> x >> y;
            cout << TD.query(x, y, p) << "\n";
        } else if (opt == 3) {
            cin >> x >> z;
            TD.updateSubtree(x, z);
        } else if (opt == 4) {
            cin >> x;
            cout << TD.querySubtree(x) << "\n";
        }
    }
}
signed main2() {
    int n, m, r, p;
    cin >> n >> m >> r >> p;
    for (int i = 1; i < n; i++) {
        int u, v;
        cin >> u >> v;
        TD.edges[u].push_back(v);
        TD.edges[v].push_back(u);
    }
    for (int i = 2; i <= n; i++)
        TD.weights[i] = 1;
    TD.init();
    while (m-- > 0) {
        string opt;
        int x, y;
        cin >> opt;
        if (opt == "P") {
            cin >> x >> y;
            TD.update(x, y, 1);
        } else {
            assert(opt == "Q");
            cin >> x >> y;
            if (TD.dfn[x] > TD.dfn[y])
                cout << TD.weights[x];  // x在下位
            else
                cout << TD.weights[y];
            cout << "\n";
        }
    }
}
signed main() {
    main1();
}

问题:

  • 只能读入三条边,读多了就RE了。
  • 莫名其妙就MLE了,未发现无穷递归(或者是孩子没看到?)
  • 线段树是好用的,没有问题。
  • 这个代码内含调试信息。

by 2018ljw @ 2023-03-11 14:43:54

@Piggy077100

要不你猜猜读入的 n 是全局变量 n 还是局部变量 n。


|