求救,样例一直输出0

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

Lindone @ 2023-03-26 19:57:15

#include <bits/stdc++.h>
using namespace std;
#define Ls (X << 1)
#define Rs (Ls | 1)
#define MAXN 100005
#define MAXEG 200005
struct Link
{
    int Y, Next;
}Graph[MAXEG];
int Nume, Head[MAXN];
int N, M, R, P;
void AddLink(int X, int Y)
{
    Graph[++Nume].Y = Y;
    Graph[Nume].Next = Head[X];
    Head[X] = Nume;
}
int A[MAXN], Val[MAXN];
struct SegmentTree
{
    int Sum[4 * MAXN], Tag[4 * MAXN];
    void Pushup(int X)
    {
        Sum[X] = (Sum[Ls] + Sum[Rs]) % P;
    }
    void Pushdown(int X, int L, int R)
    {
        int Mid = (L + R) >> 1;
        Tag[Ls] = (Tag[Ls] + Tag[X]) % P;
        Tag[Rs] = (Tag[Rs] + Tag[X]) % P;
        Sum[Ls] = (Sum[Ls] + Tag[X] * (Mid - L + 1)) % P;
        Sum[Rs] = (Sum[Rs] + Tag[X] * (R - Mid) % P) % P;
        Tag[X] = 0;
    }
    void BuildTree(int X, int L, int R)
    {
        if (L == R)
        {
            Sum[X] = Val[L];
            return;
        }
        int Mid = (L + R) >> 1;
        BuildTree(Ls, L, Mid);
        BuildTree(Rs, Mid + 1, R);
        Pushup(X);
    }
    int QueryTree(int X, int L, int R, int Start, int End)
    {
        if (R < Start || End < L) return 0;
        if (Start <= L && R <= End)
        {
            return Sum[X];
        }
        Pushdown(X, L, R);
        int Mid = (L + R) >> 1;
        return (QueryTree(Ls, L, Mid, Start, End) + QueryTree(Rs, Mid + 1, R, Start, End)) % P;
    }
    void UpdateTree(int X, int L, int R, int Start, int End, int K)
    {
        if (R < Start || End < L) return;
        if (Start <= L && R <= End)
        {
            Tag[X] = (Tag[X] + K) % P;
            Sum[X] = (Sum[X] + K * (R - L + 1) % P) % P;
            return;
        }
        Pushdown(X, L, R);
        int Mid = (L + R) >> 1;
        UpdateTree(Ls, L, Mid, Start, End, K);
        UpdateTree(Rs, Mid + 1, R, Start, End, K);
        Pushup(X);
    }
    void Build()
    {
        BuildTree(1, 1, N);
    }
    int Query(int Start, int End)
    {
        return QueryTree(1, 1, N, Start, End);
    }
    void Update(int Start, int End, int K)
    {
        UpdateTree(1, 1, N, Start, End, K);
    }
}Tree;
struct TreeChain
{
    int Time, DFN[MAXN], Son[MAXN], Size[MAXN], Depth[MAXN], Top[MAXN], Father[MAXN];
    void DFS1(int X, int Fa)
    {
        Size[X] = 1;
        Father[X] = Fa;
        Depth[X] = Depth[Fa] + 1;
        for (int i = Head[X]; i; i = Graph[i].Next)
        {
            int& Y = Graph[i].Y;
            if (Y == Fa)
                continue;
            DFS1(Y, X);
            Size[X] += Size[Y];
            if (Size[Son[X]] < Size[Y])
                Son[X] = Y;
        }
    }
    void DFS2(int X, int TopV)
    {
        Top[X] = TopV;
        Val[++Time] = A[X];
        DFN[X] = Time;
        if (!Son[X]) return;
        DFS2(Son[X], TopV);
        for (int i = Head[X]; i; i = Graph[i].Next)
        {
            int& Y = Graph[i].Y;
            if (Y == Father[X])
                continue;
            DFS2(Y, Y);
        }
    }
    void Initial()
    {
        DFS1(R, 0);
        DFS2(R, R);
        Tree.Build();
    }
    int Query(int X, int Y)
    {
        int Ans = 0;
        while (Top[X] != Top[Y])
        {
            if (Depth[Top[X]] < Depth[Top[Y]])
                swap(X, Y);
            Ans = (Ans + Tree.Query(DFN[Top[X]], DFN[X]) % P) % P;
            X = Father[Top[X]];
        }
        if (Depth[X] > Depth[Y])
            swap(X, Y);
        Ans = (Ans + Tree.Query(DFN[X], DFN[Y]) % P) % P;
        return Ans;
    }
    void Update(int X, int Y, int K)
    {
        while (Top[X] != Top[Y])
        {
            if (Depth[Top[X]] < Depth[Top[Y]])
                swap(X, Y);
            Tree.Update(DFN[Top[X]], DFN[X], K);
            X = Father[Top[X]];
        }
        if (Depth[X] > Depth[Y])
            swap(X, Y);
        Tree.Update(DFN[X], DFN[Y], K);
    }
    int QueryRoot(int X)
    {
        return Tree.Query(DFN[X], DFN[X] + Size[X] - 1);
    }
    void UpdateRoot(int X, int K)
    {
        Tree.Update(DFN[X], DFN[X] + Size[X] - 1, K);
    }
}Obj;

int main()
{
    cin >> N >> M >> R >> P;
    for (int i = 1; i <= N; ++i)
    {
        cin >> A[i];
    }
    int U, V;
    for (int i = 1; i < N; ++i)
    {
        cin >> U >> V;
        AddLink(U, V);
        AddLink(V, U);
    }
    Obj.Initial();
    int Op, X, Y, Z;
    for (int i = 1; i <= M; ++i)
    {
        cin >> Op >> X;
        if (Op == 1)
        {
            cin >> Y >> Z;
            Obj.Update(X, Y, Z);
        }
        if (Op == 2)
        {
            cin >> Y;
            cout << Obj.Query(X, Y) << endl;
        }
        if (Op == 3)
        {
            cin >> Z;
            Obj.UpdateRoot(X, Z);
        }
        if (Op == 4)
        {
            cout << Obj.QueryRoot(X) << endl;
        }
    }
    return 0;
}

by forgotmyhandle @ 2023-03-26 20:15:57

DFS2 里把重儿子算了两遍。

for 循环里的 if 应该是

if (Y == Father[X] || Y == son[X]) 
    continue;

但是你没写 || 右边。


by forgotmyhandle @ 2023-03-26 20:18:12

(如此毒瘤的数据结构写挂了居然真还有人帮忙看(笑


by Lindone @ 2023-04-23 22:00:45

@forgotmyhandle 才看到,谢谢。。。


|