37pts 求调qwq

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

InoriILU @ 2023-10-30 10:56:23

wa on 4-10\ 本地跑死循环qwq

#include <iostream>
#include <algorithm>

typedef int ET;
typedef int NT;
typedef long long DT;

struct Edge
{
    ET end, next;
};

struct Node
{
    NT depth, size, father, heavyson;
    NT rank, top;
};

const int MAXN{ 100000 + 5 };
const int MAXM{ 200000 + 5 };
int MOD{};

Edge E[MAXM]{};
ET head[MAXN]{}, count{};

Node V[MAXN]{};
NT dfn[MAXN]{}, dn{};
DT value[MAXN]{}, valOrder[MAXN]{};

void addEdge(NT start, NT end)
{
    E[++count].end = end;
    E[count].next = head[start];
    head[start] = count;
}

void dfs1(NT now, NT depth)
{
    V[now].depth = depth;
    V[now].size = 1;

    for (ET i = head[now], end{}; i; i = E[i].next)
    {
        end = E[i].end;
        if (!V[end].depth)
        {
            V[end].father = now;
            dfs1(end, depth + 1);
            V[now].size += V[end].size;
            if (V[end].size > V[V[now].heavyson].size) V[now].heavyson = end;
        }
    }
}

void dfs2(NT now, NT top)
{
    V[now].top = top;
    V[now].rank = ++dn;
    dfn[dn] = now;
    valOrder[dn] = value[now];

    if (!V[now].heavyson) return;
    dfs2(V[now].heavyson, top);

    for (ET i = head[now], end{}; i; i = E[i].next)
    {
        end = E[i].end;
        if (!V[end].rank) dfs2(end, end);
    }
}

struct SN
{
    DT val, add;
};

SN tree[MAXN * 4]{};
NT n{};

inline NT mid(NT l, NT r) { return (l + r) / 2; }
inline NT len(NT l, NT r) { return (r - l + 1); }
inline NT ls(NT now) { return now * 2; }
inline NT rs(NT now) { return now * 2 + 1; }

void make_add(NT now, DT val, NT len)
{
    tree[now].val = (tree[now].val + len * val) % MOD;
    tree[now].add = (tree[now].add + val) % MOD;
}

void push_up(NT now)
{
    tree[now].val = (tree[ls(now)].val + tree[rs(now)].val) % MOD;
    //using std::cout;
    //using std::endl;
    //cout << "-----" << endl;
    //cout << now << " " << ls(now) << " " << rs(now) << endl;
    //cout << tree[now].val << " " << tree[ls(now)].val << " " << tree[rs(now)].val << endl;
}

void push_down(NT now, NT len)
{
    if (len <= 1) return;

    make_add(ls(now), tree[now].add, len - len / 2);
    make_add(rs(now), tree[now].add, len / 2);

    tree[now].add = 0;
}

// void build(NT l = 1, NT r = size)
// {
//  NT log{};
//  for(log = 1; log < r; log <<= 1);

//  for (NT i{log}; i < log + r; i++) tree[i].val = value[i - log];
//  for (NT i{log - 1}; i >= 0; i--) push_up(i);
// }

void build(NT now = 1, NT l = 1, NT r = n)
{
    if (l == r)
    {
        tree[now].val = (valOrder[l] % MOD);
        return;
    }
    NT m{mid(l, r)};
    build(ls(now), l, m);
    build(rs(now), m + 1, r);
    push_up(now);
}

void update(NT l, NT r, DT val, NT now = 1, NT cl = 1, NT cr = n)
{
    if (l <= cl && cr <= r)
    {
        make_add(now, val, len(cl, cr));
        return;
    }
    push_down(now, len(cl, cr));
    NT m{ mid(cl, cr) };
    if (l <= m) update(l, r, val, ls(now), cl, m);
    if (m < r) update(l, r, val, rs(now), m + 1, cr);
    push_up(now);
}

DT query(NT l, NT r, NT now = 1, NT cl = 1, NT cr = n)
{
    if (l <= cl && cr <= r) return tree[now].val;
    push_down(now, len(cl, cr));
    NT m{ mid(cl, cr) };
    DT ans{};
    if (l <= m) ans += query(l, r, ls(now), cl, m);
    if (m < r) ans += query(l, r, rs(now), m + 1, cr);
    return ans;
}

DT qRange(NT x, NT y)
{
    DT ans{};
    while (V[x].top != V[y].top)
    {
        if (V[V[x].top].depth < V[V[y].top].depth) std::swap(x, y);
        ans = (ans + query(V[V[x].top].rank, V[x].rank)) % MOD;
        x = V[V[x].top].father;
    }
    if (V[x].depth > V[y].depth) std::swap(x, y);
    ans += query(V[x].rank, V[y].rank);
    return ans;
}

void updRange(NT x, NT y, DT val)
{
    val %= MOD;
    while (V[x].top != V[y].top)
    {
        if (V[V[x].top].depth < V[V[y].top].depth) std::swap(x, y);
        update(V[V[x].top].rank, V[x].rank, val);
        x = V[V[x].top].father;
    }
    if (V[x].depth > V[y].depth) std::swap(x, y);
    update(V[x].rank, V[y].rank, val);
}

DT qSon(NT now)
{
    return query(V[now].rank, V[now].rank + V[now].size - 1);
}

void updSon(NT now, DT val)
{
    update(V[now].rank, V[now].rank + V[now].size - 1, val);
}

int main()
{
    using namespace std;
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    int m{}, r{};
    int k{}, x{}, y{}, z{};
    cin >> n >> m >> r >> MOD;
    for (NT i = 1; i <= n; i++) cin >> value[i];
    for (ET i = 0, x{}, y{}; i < n - 1; i++)
    {
        cin >> x >> y;
        addEdge(x, y);
        addEdge(y, x);
    }
    dfs1(r, 1);
    dfs2(r, r);
    build();
    while (m--)
    {
        cin >> k;
        switch (k)
        {
        case 1:
            cin >> x >> y >> z;
            updRange(x, y, z);
            break;
        case 2:
            cin >> x >> y;
            cout << qRange(x, y) << endl;
            break;
        case 3:
            cin >> x >> y;
            updSon(x, y);
            break;
        case 4:
            cin >> x;
            cout << qSon(x) << endl;
            break;
        default:
            break;
        }
    }
}

by __Chx__ @ 2023-11-05 21:56:42

取模取少了:

153-155行

if (l <= m) ans += query(l, r, ls(now), cl, m);
if (m < r) ans += query(l, r, rs(now), m + 1, cr);
return ans;

168行:

ans += query(V[x].rank, V[y].rank);

把取模加上就能过了


by __Chx__ @ 2023-11-05 21:57:05

@InoriILU


by InoriILU @ 2023-11-06 14:38:12

@Chx 谢谢大哥qwq


|