CodeForces 620E New Year Tree【树链剖分】【状态压缩】【位运算】

板子题。

用一个 long long 记录一下 60 60 60 种颜色是否有了,然后直接用树链剖分统计就可以了。

可能稍微有点卡常。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 4e5 + 10;
int dep[N], fa[N];
int sz[N];
int cnt, w[N], dfs_order[N], rk[N], top[N], len[N];
int col[N];
vector<int> z[N];
int n, q;
void dfs1(int now, int fat = -1)
{
    dep[now] = dep[fa[now]] + 1;
    sz[now] = 1;
    for (auto &u : z[now])
        if (u != fat)
        {
            fa[u] = now;
            dfs1(u, now);
            sz[now] += sz[u];
        }
}
void dfs2(int now, int head, int fa = -1)
{
    cnt++;
    w[cnt] = 1ll << col[now];
    dfs_order[cnt] = now;
    rk[now] = cnt;
    top[now] = head;
    len[head]++;
    int p = -1;
    for (auto &u : z[now])
    {
        if (u == fa)
            continue;
        if (p == -1)
            p = u;
        else if (sz[u] > sz[p])
            p = u;
    }
    if (p == -1)
        return;
    dfs2(p, head, now);
    for (auto &j : z[now])
        if (p != j && j != fa)
            dfs2(j, j, now);
}

struct Node
{
    int l, r, sum, lazy;
    Node()
    {
        l = r = sum = lazy = 0;
    }
    ~Node()
    {
        l = r = sum = lazy = 0;
    }
    void init(int p)
    {
        l = r = p;
        sum = w[p];
        lazy = 0;
    }
    void color(int p)
    {
        sum = p;
        lazy = p;
    }
} y[N << 2];

Node operator+(const Node &lhs, const Node &rhs)
{
    Node res;
    res.l = lhs.l;
    res.r = rhs.r;
    res.sum = lhs.sum | rhs.sum;
    res.lazy = 0;
    return res;
}

void build(int l, int r, int rt)
{
    if (l == r)
        y[rt].init(l);
    else
    {
        int mid = l + r >> 1;
        build(l, mid, rt << 1);
        build(mid + 1, r, rt << 1 | 1);
        y[rt] = y[rt << 1] + y[rt << 1 | 1];
    }
}

void push_lazy(int rt)
{
    if (y[rt].lazy)
    {
        y[rt << 1].color(y[rt].lazy);
        y[rt << 1 | 1].color(y[rt].lazy);
        y[rt].lazy = 0;
    }
}

void modify(int l, int r, int rt, int nowl, int nowr, int value)
{
    if (nowl <= l && r <= nowr)
        y[rt].color(value);
    else
    {
        int mid = l + r >> 1;
        push_lazy(rt);
        if (nowl <= mid)
            modify(l, mid, rt << 1, nowl, nowr, value);
        if (mid < nowr)
            modify(mid + 1, r, rt << 1 | 1, nowl, nowr, value);
        y[rt] = y[rt << 1] + y[rt << 1 | 1];
    }
}

int query(int l, int r, int rt, int nowl, int nowr)
{
    if (nowl <= l && r <= nowr)
        return y[rt].sum;
    int mid = l + r >> 1;
    push_lazy(rt);
    int sum = 0;
    if (nowl <= mid)
        sum |= query(l, mid, rt << 1, nowl, nowr);
    if (mid < nowr)
        sum |= query(mid + 1, r, rt << 1 | 1, nowl, nowr);
    return sum;
}

int query_tree(int p)
{
    return query(1, n, 1, rk[p], rk[p] + sz[p] - 1);
}

void modify_tree(int p, int value)
{
    modify(1, n, 1, rk[p], rk[p] + sz[p] - 1, 1ll << value);
}
signed main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        cin >> col[i];
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        z[u].push_back(v);
        z[v].push_back(u);
    }
    dfs1(1);
    dfs2(1, 0);
    build(1, n, 1);
    while (q--)
    {
        int o;
        cin >> o;
        if (o == 1)
        {
            int u, c;
            cin >> u >> c;
            modify_tree(u, c);
        }
        else
        {
            int u;
            cin >> u;
            cout << __builtin_popcountll(query_tree(u)) << '\n';
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值