Codeforces620E New Year Tree

挺好的一道题

Description

link

给一棵树,每个点有颜色 \(c_i\) 为点权,需要实现以下两种操作:

子树修改颜色(覆盖),查询子树颜色种类

\(n \leq 4 \times 10^5,c_i \leq 60\)

Solution

\[Begin\]

首先看到子树和修改啥的,直接思考 \(dfs\) 序加线段树(从树剖学来的)

我们看到如果对于每一个点开桶进行统计,可能不太现实

然后审题的关键点就来了:\(c_i \leq 60\)

可以开 $long $ \(long\) 状压

然后就成了单点进行答案统计

最后把对应 \(query\) 搞个 \(lowbit\) 什么的整一下 \(1\) 就好了(从树状数组剽来的)

要注意 \(1ll<<\)的问题(蒟蒻去年没有遇到这种问题,因为\(D1T1\)写的暴力……)

\[Q.A.D\]

\(P.S.\)博主知道应该是\(QED\)

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm {
inline int read() {
    int res = 0, f = 1;
    char k;
    while (!isdigit(k = getchar()))
        if (k == '-')
            f = -1;
    while (isdigit(k)) res = res * 10 + k - '0', k = getchar();
    return res * f;
}
const int N = 4e5 + 10;
int a[N], fa[N], dep[N], head[N], cnt, in[N], out[N], tim, opt, n, m, id[N];
struct node {
    int nxt, to;
} e[N << 2];
inline void add1(int u, int v) {
    e[++cnt].nxt = head[u];
    e[cnt].to = v;
    return head[u] = cnt, void();
}
struct tree {
    int l, r, sum, add;
#define l(p) t[p].l
#define r(p) t[p].r
#define sum(p) t[p].sum
#define add(p) t[p].add
} t[N << 2];
inline void push_up(int p) {
    sum(p) = sum(p << 1) | sum(p << 1 | 1);
    return;
}
inline void build(int p, int l, int r) {
    l(p) = l;
    r(p) = r;
    if (l == r)
        return sum(p) = 1ll << a[id[l]], void();
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    return push_up(p);
}
inline int lowbit(int x) { return x & (-x); }
inline void spread(int p) {
    if (add(p)) {
        sum(p << 1) = add(p);
        sum(p << 1 | 1) = add(p);
        add(p << 1) = add(p);
        add(p << 1 | 1) = add(p);
    }
    return add(p) = 0, void();
}
inline void update(int p, int l, int r, int c) {
    if (l <= l(p) && r(p) <= r)
        return add(p) = 1ll << c, sum(p) = 1ll << c, void();
    spread(p);
    int mid = (l(p) + r(p)) >> 1;
    if (l <= mid)
        update(p << 1, l, r, c);
    if (r > mid)
        update(p << 1 | 1, l, r, c);
    return push_up(p);
}
inline int query(int p, int l, int r) {
    if (l <= l(p) && r(p) <= r)
        return sum(p);
    spread(p);
    int ans = 0, mid = (l(p) + r(p)) >> 1;
    if (l <= mid)
        ans |= query(p << 1, l, r);
    if (r > mid)
        ans |= query(p << 1 | 1, l, r);
    return ans;
}
inline int ask1(int x) {
    int ret = 0;
    for (; x; x -= lowbit(x)) ret++;
    return ret;
}
inline void dfs(int x, int f) {
    in[x] = ++tim;
    id[tim] = x;
    fa[x] = f;
    for (int i = head[x]; i; i = e[i].nxt) {
        int t = e[i].to;
        if (t == f)
            continue;
        dfs(t, x);
    }
    return out[x] = tim, void();
}
signed main() {
    n = read(), m = read();
    for (int i = 1; i <= n; ++i) a[i] = read();
    for (int i = 1, u, v; i < n; ++i) u = read(), v = read(), add1(u, v), add1(v, u);
    dfs(1, 0);
    build(1, 1, n);
    while (m--) {
        opt = read();
        if (opt == 1) {
            int x = read(), c = read();
            update(1, in[x], out[x], c);
        } else {
            int x = read();
            int tmp = query(1, in[x], out[x]);
            printf("%lld\n", ask1(tmp));
        }
    }
    return 0;
}
}  // namespace yspm
signed main() { return yspm::main(); }

猜你喜欢

转载自www.cnblogs.com/yspm/p/12369912.html