悬关求调
查看原帖
悬关求调
1053871
cloud_windl楼主2024/10/24 00:13
#include <bits/stdc++.h>
using namespace std;

#define inf 0x3f3f3f3f
#define int long long
#define lc u << 1
#define rc u << 1 | 1

const int maxn = 100100;

int w[maxn];
vector<int> e[maxn];
int dep[maxn], son[maxn], top[maxn], sz[maxn], fa[maxn];
int cnt, id[maxn], nw[maxn];
int Lc, Rc;

struct tree
{
    int l, r;
    int tag, sum;
    int dl, dr;
} tr[4 * maxn];

void pushup(int u)
{
    tr[u].sum = tr[lc].sum + tr[rc].sum;
    tr[u].dl = tr[lc].dl;
    tr[u].dr = tr[rc].dr;
    if (tr[lc].dr == tr[rc].dl)
        tr[u].sum--;
}

void pushdown(int u)
{
    if (tr[u].tag)
    {
        tr[lc].sum = 1;
        tr[rc].sum = 1;
        tr[lc].tag = tr[u].tag;
        tr[rc].tag = tr[u].tag;
        tr[lc].dl = tr[u].dl;
        tr[lc].dr = tr[u].dl;
        tr[rc].dl = tr[u].dl;
        tr[lc].dr = tr[u].dl;
        tr[u].tag = 0;
    }
}

void update(int u, int l, int r, int k)
{
    if (l <= tr[u].l && tr[u].r <= r)
    {
        tr[u].sum = 1;
        tr[u].tag = 1;
        tr[u].dl = k;
        tr[u].dr = k;
        return;
    }
    pushdown(u);
    int mid = (tr[u].l + tr[u].r) >> 1;
    if (r <= mid)
        update(lc, l, r, k);
    else if (l > mid)
        update(rc, l, r, k);
    else
    {
        update(lc, l, mid, k);
        update(rc, mid + 1, r, k);
    }
    pushup(u);
}

void update_path(int u, int v, int k)
{
    while (top[u] != top[v])
    {
        if (dep[top[u]] < dep[top[v]])
            swap(u, v);
        update(1, id[top[u]], id[u], k);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v])
        swap(u, v);
    update(1, id[v], id[u], k);
}

int query(int u, int l, int r, int L, int R)
{
    if (tr[u].l == L)
        Lc = tr[u].dl;
    if (tr[u].r == R)
        Rc = tr[u].dr;
    if (l <= tr[u].l && tr[u].r <= r)
        return tr[u].sum;
    pushdown(u);
    int res = 0;
    int mid = (tr[u].l + tr[u].r) >> 1;
    if (r <= mid)
        return query(lc, l, r, L, R);
    else if (l > mid)
        return query(rc, l, r, L, R);
    else
    {
        res = query(lc, l, mid, L, R) + query(rc, mid + 1, r, L, R);
        if (tr[lc].dr == tr[rc].dl)
            res--;
        return res;
    }
}

int query_path(int u, int v)
{
    int res = 0;
    int ans1 = -1, ans2 = -1;
    while (top[u] != top[v])
    {
        if (dep[top[u]] < dep[top[v]])
            swap(u, v), swap(ans1, ans2);
        res += query(1, id[top[u]], id[u], id[top[u]], id[u]);
        if (Rc == ans1)
            res--;
        ans1 = Lc;
        u = fa[top[u]];
    }
    if (dep[u] < dep[v])
    {
        swap(u, v);
        swap(ans1, ans2);
    }
    res += query(1, id[v], id[u], id[v], id[u]);
    if (Rc == ans1)
        res--;
    if (Lc == ans2)
        res--;
    return res;
}

void build(int u, int l, int r)
{
    tr[u] = {l, r, 0, 0, nw[l], nw[r]};
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    // pushup(u);
}

void dfs1(int u, int f)
{
    dep[u] = dep[f] + 1, sz[u] = 1, fa[u] = f;
    for (int v : e[u])
    {
        if (v == f)
            continue;
        dfs1(v, u);
        sz[u] += sz[v];
        if (sz[son[u]] < sz[v])
            son[u] = v;
    }
}

void dfs2(int u, int t)
{
    top[u] = t, id[u] = ++cnt, nw[cnt] = w[u];
    if (!son[u])
        return;
    dfs2(son[u], t);
    for (int v : e[u])
    {
        if (v == fa[u] || v == son[u])
            continue;
        dfs2(v, v);
    }
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> w[i];
    for (int i = 1, u, v; i < n; i++)
    {
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs1(1, 1);
    dfs2(1, 1);
    build(1, 1, n);
    for (int i = 1; i <= n; i++)
        update(1, id[i], id[i], w[i]);
    char op;
    int a, b, c;
    while (m--)
    {
        cin >> op;
        if (op == 'C')
        {
            cin >> a >> b >> c;
            update_path(a, b, c);
        }
        else
        {
            cin >> a >> b;
            cout << query_path(a, b) << '\n';
        }
    }
    return 0;
}
2024/10/24 00:13
加载中...