萌新求调树链剖分
查看原帖
萌新求调树链剖分
1369607
luckyqwq楼主2024/8/30 11:54
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, m, rt, mod, cnt, tp, ans, a[N], fa[N], Head[N << 1], to[N << 1], nex[N << 1], son[N], siz[N], dfn[N], rnk[N], dep[N], top[N], tre[N << 2], lazy[N << 2], dir[N << 2];
inline int read()
{
    int r = 0, w = 1;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        r = (r << 3) + (r << 1) + (ch ^ 48);
        ch = getchar();
    }
    return r * w;
}
void add(int x, int y)
{
    nex[++ cnt] = Head[x];
    Head[x] = cnt;
    to[cnt] = y;
}
void dfs1(int u, int f)
{
    son[u] = -1;//初始化无重儿子
    siz[u] = 1;
    for (int i = Head[u]; i ; i = nex[i])
    {
        int v = to[i];
        if(v ^ f)
        {
            dep[v] = dep[u] + 1;
            fa[v] = u;
            dir[i / 2] = v;
            dfs1(v, u);
            siz[u] += siz[v];
            if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
        }
    }
}
void dfs2(int x, int fath)
{
    top[x] = fath;
    dfn[x] = ++ tp;
    rnk[tp] = x;
    if (son[x] == -1) return;//叶子节点
    dfs2 (son[x], fath);
    for (int i = Head[x]; i ; i = nex[i])
    {
        int v = to[i];
        if (v != fa[x] && v != son[x]) dfs2(v, v);
    }
}
void pushup(int x)
{
    tre[x] = (tre[x << 1] + tre[x << 1 | 1]) % mod;
}
void pushdown(int x, int l, int r)
{
    if (lazy[x])
    {
        lazy[x << 1] += lazy[x];
        lazy[x << 1 | 1] += lazy[x];
        tre[x << 1] += lazy[x] * ((r - l + 1) - ((r - l + 1) >> 1));
        tre[x << 1] %= mod;
        tre[x << 1 | 1] += lazy[x] * ((r - l + 1) >> 1);
        tre[x << 1 | 1] %= mod;
        lazy[x] = 0;
    }
    return;
}
void build(int x, int l, int r)
{
    if (!(l ^ r))
    {
        tre[x] = a[rnk[l]] % mod;
        return;
    }
    int mid = l + r >> 1;
    build(x << 1, l, mid);
    build(x << 1 | 1, mid + 1, r);
    pushup(x);
}
void update(int x, int l, int r, int u, int v, int w)
{
    
    if (u <= l && r <= v)
    {
        lazy[x] += w;
        tre[x] += w * (r - l + 1);
        tre[x] %= mod;
        return;
    }
    int mid = l + r >> 1;
    if (u <= mid) update(x << 1, l, mid, u, v, w);
    if (v > mid) update(x << 1 | 1, mid + 1, r, u, v, w);
    pushup(x);
}
void query (int x, int l, int r, int u, int v)
{
    if (!(l ^ r))
    {
        ans += tre[x];
        ans %= mod;
        return;
    }
    int mid = l + r >> 1;
    pushdown(x, l, r);
    if (u <= mid) query(x << 1, l, mid, u, v);
    if (v > mid) query(x << 1 | 1, mid + 1, r, u, v);
}
void zsupdate(int x, int w)
{
    update (1, 1, n, dfn[x], dfn[x] + siz[x] - 1, w);
}
int fastquery(int x, int y)
{
    int res = 0;
    while (top[x] ^ top[y])
    {
        if (dep[top[x]] < dep[top[y]])
        { 
            swap(x, y);
        }
        ans = 0;
        query(1, 1, n, dfn[top[x]], dfn[x]);
        res = (res + ans) % mod;
        x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    ans = 0;
    query(1, 1, n, dfn[x], dfn[y]);
    res = (res + ans) % mod;
    return res;
}
signed main()
{
    n = read();
    m = read();
    mod = 1e18;
    for (int i = 1;i <= n; ++ i)
    {
        a[i] = read();
    }
    for (int i = 1; i < n; ++ i)
    {
        int u = read(), v = read();
        add(u, v);
        add(v, u);
    }
    dfs1 (1, 0);
    dfs2 (1, 1);
    build (1, 1, n);
    while (m --)
    {
        int op = read();
        if (op == 1)
        {
            int x = read(), w = read();
            update(1, 1, n, dfn[x], dfn[x], w);
        }
        else if (op == 2)
        {
            int x = read(), y = read();
            zsupdate (x, y);
        }
        else
        {
            int x = read();
            printf("%lld\n", fastquery(1, x));
        }
    }
    return 0;
}

TLE 50,感觉不应该超时吧。

2024/8/30 11:54
加载中...