mxqz
查看原帖
mxqz
384214
esquigybcu楼主2021/11/3 17:50

RTRT,写了一下午的树剖挂了

#include <stdio.h>
#include <string.h>
#include <algorithm>

typedef long long ll;
const ll N = 1e5 + 5;
ll MOD;

struct node
{
    ll l, r, sum, lazy;
};
struct segtree
{
    node tree[N << 2];

    #define u tree[i]
    #define lc tree[i << 1]
    #define rc tree[i << 1 | 1]
    #define len(x) (x.r - x.l)

    inline void pushup(ll i)
    {
        if (len(u) == 0) return;
        u.sum = lc.sum + rc.sum;
        u.sum %= MOD;
    }

    inline void pushdown(ll i)
    {
        if (len(u) == 0) return;
        lc.sum += len(lc) * u.lazy; lc.sum %= MOD;
        lc.lazy += u.lazy;          lc.lazy %= MOD;
        rc.sum += len(rc) * u.lazy; rc.sum %= MOD;
        rc.lazy += u.lazy;          rc.lazy %= MOD;
    }

    inline void build(ll a[], ll i, ll l, ll r)
    {
        u.l = l, u.r = r, u.lazy = 0;
        if (len(u) == 1)
        {
            u.sum = a[l] % MOD;
            return;
        }
        ll mid = (l + r) >> 1;
        build(a, i << 1, l, mid);
        build(a, i << 1 | 1, mid, r);
        pushup(i);
    }

    inline ll query(ll i, ll l, ll r)
    {
        if (len(u) == 0) return 0;
        if (l == u.l && r == u.r)
            return u.sum;
        
        pushdown(i);
        ll mid = (u.l + u.r) >> 1;
        if (r <= mid)
            return query(i << 1, l, r);
        if (l >= mid)
            return query(i << 1 | 1, l, r);
        return (query(i << 1, l, mid) + query(i << 1 | 1, mid, r)) % MOD;
    }

    inline void modify(ll i, ll l, ll r, ll k)
    {
        if (len(u) == 0) return;
        if (l == u.l && r == u.r)
        {
            u.lazy += k, u.sum += len(u) * k;
            u.lazy %= MOD, u.sum %= MOD;
            return;
        }

        ll mid = (u.l + u.r) >> 1;
        if (r <= mid)
            modify(i << 1, l, r, k);
        else if (l >= mid)
            modify(i << 1 | 1, l, r, k);
        else
            modify(i << 1, l, mid, k), modify(i << 1 | 1, mid, r, k);
    }

    #undef u
    #undef lc
    #undef rc
    #undef len
}
QwQ;

struct edge
{
    ll u, v, next;
}
e[2 * N]; ll cnt, head[N];
inline void add_edge(ll u, ll v)
{
    e[cnt].u = u, e[cnt].v = v, e[cnt].next = head[u];
    head[u] = cnt++;
}

ll father[N], depth[N], size[N], hson[N];
ll top[N], dfn[N], rank[N], dfscnt;

void dfs1(ll u, ll f)
{
    father[u] = f;
    depth[u] = depth[f] + 1;
    size[u] = 1;
    
    ll qwq = 0;
    for (int i = head[u]; ~i; i = e[i].next)
        if (e[i].v != f)
        {
            ll v = e[i].v;
            dfs1(v, u);
            size[u] += size[v];
            if (size[v] > qwq)
                qwq = size[v], hson[u] = v;
        }
}

void dfs2(ll u, ll a) // a 为链顶
{
    top[u] = a;
    dfn[u] = dfscnt; rank[dfscnt++] = u;

    dfs2(hson[u], a);
    for (int i = head[u]; ~i; i = e[i].next)
        if (e[i].v != father[u] && e[i].v != hson[u])
            dfs2(e[i].v, e[i].v);
}

inline ll chain_query(ll u, ll v)
{
    ll ans = 0;
    while (top[u] != top[v])
    {
        if (depth[top[u]] < depth[top[v]])
            std::swap(u, v);
        ans += QwQ.query(1, dfn[top[u]], dfn[u] + 1); ans %= MOD;
        u = father[top[u]];
    }
    return ans;
}

inline void chain_modify(ll u, ll v, ll k)
{
    while (top[u] != top[v])
    {
        if (depth[top[u]] < depth[top[v]])
            std::swap(u, v);
        QwQ.modify(1, dfn[top[u]], dfn[u] + 1, k);
        u = father[top[u]];
    }
}

inline ll subtree_query(ll u)
{
    return QwQ.query(1, dfn[u], dfn[u] + size[u]);
}

inline void subtree_modify(ll u, ll k)
{
    QwQ.modify(1, dfn[u], dfn[u] + size[u], k);
}

ll init[N];

int main()
{
    memset(head, -1, sizeof head);
    ll n, q, rt;
    scanf("%lld %lld %lld %lld", &n, &q, &rt, &MOD);

    for (int i = 1; i <= n; i++)
        scanf("%lld", &init[i]);
    QwQ.build(init, 1, 1, n + 1);

    for (int i = 0; i < n - 1; i++)
    {
        ll u, v;
        scanf("%lld %lld", &u, &v);
        add_edge(u, v), add_edge(v, u);
    }

    dfs1(rt, 0);
    dfs2(rt, rt);

    while (q--)
    {
        ll op, x, y, k;
        scanf("%lld", &op);
        if (op == 1)
        {
            scanf("%lld %lld %lld", &x, &y, &k);
            chain_modify(x, y, k);
        }
        if (op == 2)
        {
            scanf("%lld %lld", &x, &y);
            printf("%lld\n", chain_query(x, y));
        }
        if (op == 3)
        {
            scanf("%lld %lld", &x, &k);
            subtree_modify(x, k);
        }
        if (op == 4)
        {
            scanf("%lld", &x);
            printf("%lld\n", subtree_query(x));
        }
    }
    return 0;
}
2021/11/3 17:50
加载中...