CodeForces620E New Year Tree 61 线段树 状态压缩

题意

  • 给你一棵树,支持两个操作,\(1\)把一个子树的颜色更改为\(c\)\(2\)是询问一个子树内的颜色数,颜色数\(<=60\)

观察到颜色数不超过\(long\ long\)

可以把颜色压成一个长整形数

利用\(dfs\)序把树上操作变成区间操作

用线段树维护即可

有一个要注意的地方

__builtin_popcount 默认为\(int\)

要调用__builtin_popcountll

Codes

#include <bits/stdc++.h>

using namespace std;

#define For(i, a, b) for (register int i = (a), i##_end = b; i <= i##_end; ++ i) 
#define FOR(i, a, b) for (register int i = (a), i##_end = b; i >= i##_end; -- i) 
#define go(x, i) for (register int i = head[x]; i; i = nxt[i])
#define getc getchar_unlocked
#define putc putchar_unlocked
#define inf (0x3f3f3f3f)
#define INF (2e18)
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define y1 igniubi

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef long double ldb;
typedef double db;
typedef pair<int, int> PII;
typedef pair<ll, int> PLI;

inline void procStatus() {
    ifstream t("/proc/self/status");
    cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>());
}

const int N = 4e5 + 10;

int to[N << 1], nxt[N << 1], head[N], e;
int a[N], st[N], ed[N], rel[N], n, q, cnt;

void add(int x, int y) {
    to[++ e] = y; nxt[e] = head[x]; head[x] = e; 
}

void dfs(int x, int dad) {
    rel[st[x] = ++ cnt] = x; 
    go(x, i) if(to[i] ^ dad) 
        dfs(to[i], x);
    ed[x] = cnt;
}

struct Segment_Tree {
#define ls (bh << 1)
#define rs (ls | 1)
#define mid ((l + r) >> 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
    ll S[N << 2], tag[N << 2];
    
    void pushup(int bh) {
        S[bh] = S[ls] | S[rs];
    }

    void pushdown(int bh) {
        if (tag[bh]) S[ls] = S[rs] = tag[ls] = tag[rs] = tag[bh], tag[bh] = 0;
    }

    void build(int bh, int l, int r) {
        if (l == r) S[bh] = 1ll << (a[rel[l]] - 1);
        else build(lson), build(rson), pushup(bh);
    }

    void update(int bh, int l, int r, int x, int y, int z) {
        if (x <= l && r <= y) 
            S[bh] = tag[bh] = 1ll << (z - 1); 
        else {
            pushdown(bh);
            if (x <= mid) update(lson, x, y, z);
            if (y > mid) update(rson, x, y, z);
            pushup(bh);
        }
    }

    ll query(int bh, int l, int r, int x, int y) {
        if (x <= l && r <= y) return S[bh];
        pushdown(bh);
        if (x > mid) return query(rson, x, y);
        if (y <= mid) return query(lson, x, y);
        return query(lson, x, y) | query(rson, x, y);
    }

}T;

int main() {
    //freopen("CF620E.in", "r", stdin);
    //freopen("CF620E.out", "w", stdout);

    int opt, x, y;

    scanf("%d%d", &n, &q);
    For(i, 1, n) scanf("%d", &a[i]);
    For(i, 2, n) {
        scanf("%d%d", &x, &y);
        add(x, y), add(y, x);
    }
    dfs(1, 0), T.build(1, 1, n);

    while (q --) {
        scanf("%d%d", &opt, &x);
        if (opt == 1) scanf("%d", &y), T.update(1, 1, n, st[x], ed[x], y);
        else printf("%d\n", __builtin_popcountll(T.query(1, 1, n, st[x], ed[x])));
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/brunch/p/9930418.html