DFS序+线段树+bitset CF 620E New Year Tree(圣诞树)

 

题目链接

题意:

  一棵以1为根的树,树上每个节点有颜色标记(<=60),有两种操作:

  1. 可以把某个节点的子树的节点(包括本身)都改成某种颜色

  2. 查询某个节点的子树上(包括本身)有多少个不同的颜色

思路:

  和2012年多校第7场的G题是同类题,DFS序处理出每个节点管辖的管辖范围[L[u], R[u]],其中L[u]就是子树根节点u所在的位置,用线段树成端更新颜色变化,注意到颜色(<=60),可以用bitset<60>,0表示没有这个颜色,1表示有,异或就能区间合并,最后count一下不同颜色的个数。

另外:

  以前这种题是做不了的,现在都能秒掉了,说明在进步:)

#include <bits/stdc++.h>

const int N = 4e5 + 5;
int a[N];
std::vector<int> edge[N];
int L[N], R[N], id[N];
int tim;

#define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
struct Node {
    std::bitset<60> color;
    int lazy;
};
Node node[N<<2];

void push_up(int o) {
    node[o].color = node[o<<1].color | node[o<<1|1].color;
}

void push_down(int o) {
    if (node[o].lazy != -1) {
        node[o<<1].lazy = node[o<<1|1].lazy = node[o].lazy;
        node[o<<1].color.reset ();
        node[o<<1].color.set (node[o].lazy);
        node[o<<1|1].color.reset ();
        node[o<<1|1].color.set (node[o].lazy);
        node[o].lazy = -1;
    }
}

void build(int l, int r, int o) {
    node[o].lazy = -1;
    node[o].color.reset ();  //clear to 0
    if (l == r) {
        node[o].color.set (a[id[l]]);  //set to 1
        return ;
    }
    int mid = l + r >> 1;
    build (lson);
    build (rson);
    push_up (o);
}

void updata(int ql, int qr, int c, int l, int r, int o) {
    if (ql <= l && r <= qr) {
        node[o].lazy = c;
        node[o].color.reset ();
        node[o].color.set (c);
        return ;
    }
    push_down (o);
    int mid = l + r >> 1;
    if (ql <= mid) {
        updata (ql, qr, c, lson);
    }
    if (qr > mid) {
        updata (ql, qr, c, rson);
    }
    push_up (o);
}

std::bitset<60> query(int ql, int qr, int l, int r, int o) {
    if (ql <= l && r <= qr) {
        return node[o].color;
    }
    push_down (o);
    int mid = l + r >> 1;
    std::bitset<60> ret;
    if (ql <= mid) {
        ret |= query (ql, qr, lson);
    }
    if (qr > mid) {
        ret |= query (ql, qr, rson);
    }
    return ret;
}

void DFS(int u, int fa) {
    L[u] = ++tim; id[tim] = u;
    for (auto v: edge[u]) {
        if (v != fa) {
            DFS (v, u);
        }
    }
    R[u] = tim;
}

int main() {
    int n, m;
    scanf ("%d%d", &n, &m);
    for (int i=1; i<=n; ++i) {
        scanf ("%d", a+i);
        a[i]--;
    }
    for (int i=1; i<n; ++i) {
        int x, y;
        scanf ("%d%d", &x, &y);
        edge[x].push_back (y);
        edge[y].push_back (x);
    }
    tim = 0;
    DFS (1, 0);
    build (1, tim, 1);

    for (int i=0; i<m; ++i) {
        int type, v;
        scanf ("%d%d", &type, &v);
        if (type == 1) {
            int c;
            scanf ("%d", &c);
            c--;
            updata (L[v], R[v], c, 1, tim, 1);
        } else {
            std::bitset<60> ans = query (L[v], R[v], 1, tim, 1);
            printf ("%d\n", ans.count ());
        }
    }
    return 0;
}

  

posted @ 2016-07-11 10:39  Running_Time  阅读(261)  评论(0编辑  收藏  举报