P5314 [Ynoi2011] ODT 题解

lxl 说过邻域信息维护父亲一定死,所以考虑对每个点维护其所有儿子构成的平衡树,

发现这样还是不行,于是对每个点维护其所有轻儿子构成的平衡树,

发现这样就可以了,因为每次链加只会修改 $O(\log n)$ 个点的平衡树。

在维护平衡树的过程中需要单点求值,再维护个树状数组即可。

俩 $\log$ 跑 1e6 直接松过去了 /jy

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
inline int R()
{
    int q = 0;
    char c = getchar();
    while (c < '0' || c > '9')
        c = getchar();
    while (c >= '0' && c <= '9')
        q = q * 10 + c - '0', c = getchar();
    return q;
}
struct E
{
    int v, t;
} e[2000050];
int n, m, c, _, a[1000050], z[1000050], d[1000050], f[1000050], s[1000050], t[1000050], b[1000050], h[1000050], C[1000050], _C[1000050];
struct T
{
    T *l, *r;
    int v, k, s;
    T(int _v) : l(0), r(0), v(_v), k(rand()), s(1) {}
    void p()
    {
        s = 1;
        if (l)
            s += l->s;
        if (r)
            s += r->s;
    }
} * r[1000050];
void G(int x, int k)
{
    for (; x <= n; x += x & -x)
        C[x] += k;
}
int Q(int x)
{
    int q = 0;
    for (; x; x &= x - 1)
        q += C[x];
    return q;
}
void A(int u, int v) { e[++c] = {v, h[u]}, h[u] = c; }
void X(int u, int k)
{
    s[u] = 1;
    for (int i = h[u], v; i; i = e[i].t)
        if ((v = e[i].v) != k)
        {
            d[v] = d[f[v] = u] + 1;
            X(v, u);
            s[u] += s[v];
            if (s[v] > s[z[u]])
                z[u] = v;
        }
}
void Y(int u, int g)
{
    t[u] = g;
    b[u] = ++_;
    if (z[u])
        Y(z[u], g);
    for (int i = h[u], v; i; i = e[i].t)
        if ((v = e[i].v) != f[u] && v != z[u])
            Y(v, v);
}
void S(T *x, int k, T *&a, T *&b)
{
    if (!x)
        return a = b = 0, void();
    if (x->v > k)
        b = x, S(x->l, k, a, b->l), b->p();
    else
        a = x, S(x->r, k, a->r, b), a->p();
}
T *M(T *a, T *b)
{
    if (!a)
        return b;
    if (!b)
        return a;
    if (a->k < b->k)
        return a->r = M(a->r, b), a->p(), a;
    else
        return b->l = M(a, b->l), b->p(), b;
}
void I(T *&r, int v)
{
    T *a, *b;
    S(r, v, a, b);
    r = M(a, M(new T(v), b));
}
void D(T *&r, int v)
{
    T *a, *b, *c;
    S(r, v, a, c);
    S(a, v - 1, a, b);
    r = M(a, M(b->l, M(b->r, c)));
    delete b;
}
int K(T *x, int v)
{
    int z = x->l ? x->l->s : 0;
    if (v == z + 1)
        return x->v;
    if (v <= z)
        return K(x->l, v);
    else
        return K(x->r, v - z - 1);
}
int main()
{
    n = R(), m = R();
    for (int i = 1; i <= n; ++i)
        a[i] = R();
    for (int i = 1, u, v; i < n; ++i)
        u = R(), v = R(), A(u, v), A(v, u);
    X(1, 0);
    Y(1, 1);
    for (int i = 1; i <= n; ++i)
        C[b[i]] += a[i], C[b[i] + 1] -= a[i];
    for (int i = 1; i <= n; ++i)
        _C[i] = _C[i - 1] + C[i], C[i] = _C[i] - _C[i & i - 1];
    for (int u = 1; u <= n; ++u)
        for (int i = h[u], v; i; i = e[i].t)
            if ((v = e[i].v) != f[u] && v != z[u])
                I(r[u], a[v]);
    for (int i = 0, o, x, y, k; i < m; ++i)
    {
        o = R(), x = R(), y = R();
        if (o & 1)
        {
            k = R();
            while (t[x] != t[y])
            {
                if (d[t[x]] < d[t[y]])
                    swap(x, y);
                D(r[f[t[x]]], Q(b[t[x]]));
                G(b[t[x]], k);
                G(b[x] + 1, -k);
                I(r[f[t[x]]], Q(b[t[x]]));
                x = f[t[x]];
            }
            if (b[x] > b[y])
                swap(x, y);
            if (f[x] && x == t[x])
                D(r[f[x]], Q(b[x]));
            G(b[x], k);
            G(b[y] + 1, -k);
            if (f[x] && x == t[x])
                I(r[f[x]], Q(b[x]));
        }
        else
        {
            I(r[x], Q(b[x]));
            if (f[x])
                I(r[x], Q(b[f[x]]));
            if (z[x])
                I(r[x], Q(b[z[x]]));
            printf("%d\n", K(r[x], y));
            D(r[x], Q(b[x]));
            if (f[x])
                D(r[x], Q(b[f[x]]));
            if (z[x])
                D(r[x], Q(b[z[x]]));
        }
    }
    return 0;
}
posted @ 2024-02-02 22:06  5k_sync_closer  阅读(20)  评论(0编辑  收藏  举报  来源