CF--- PROBLEM 620 E 【思维 + DFS序 + 二进制状态】

来源:互联网 发布:中国保险保险网络大学 编辑:程序博客网 时间:2024/06/05 21:49

传送门
//题意: 对于一棵树以1为根的树, 每个结点有一种颜色. 现在有两种操作.
1 x y 把以x为根节点的子树中的所有节点染成颜色y
2 x 询问以x为根节点的子树中有多少种颜色的节点
//思路: 很明显的DFS序, 需要考虑几点, 涉及到线段树的区间修改. 然后就是颜色的计数, 由于颜色最多60种, 那么用long long 的二进制来表示它的颜色. 这样再pushup时直接左右子树或起来就行. 注意一个坑点就是在DFS序中的线段树描述的是各个节点的序了!!! 不再是每一个节点本身. 所以在build中, tree[id].val = a[dfsxu[l]] (dfsxu表示的是当前节点在dfs序中代表的节点!!!), 而不是a[l] !!! 这个BUG调了我好久. 要多做做这方面的题啊.

AC Code

/** @Cain*/const int maxn = 4e5+5;int cas=1;ll a[maxn];int dfs_xx[maxn];struct node{    int tl, tr; ll val, maxx, lazy;    void fun(ll tmp) {      //如果是直接加值就用 +=        lazy = tmp;        val = 1ll<<(tmp-1);        //maxx = tmp;    }} tree[maxn*4];void pushup(int id){    tree[id].val = tree[id<<1].val|tree[id<<1|1].val;    //tree[id].maxx = max(tree[id<<1].maxx,tree[id<<1|1].maxx);}void pushdown(int id){    if(tree[id].lazy){        tree[id<<1].fun(tree[id].lazy);        tree[id<<1|1].fun(tree[id].lazy);        tree[id].lazy = 0;    }}void build(int id,int l,int r){    tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0;    if(l == r){        tree[id].val = a[dfs_xx[l]];  //这是一个坑点啊.就如上面我所说.        return ;    }    int mid = (l+r) >> 1;    build(id<<1,l,mid);    build(id<<1|1,mid+1,r);    pushup(id);}void update(int id,int st,int ed,int val){    int l=tree[id].tl, r=tree[id].tr;    if(st <= l && r <= ed){        tree[id].fun(val);        return ;    }    pushdown(id);    int mid = (l+r) >> 1;    if(st <= mid) update(id<<1,st,ed,val);    if(ed > mid) update(id<<1|1,st,ed,val);    pushup(id);}ll query(int id,int ql,int qr){    int l = tree[id].tl , r = tree[id].tr;    if(ql <= l && r <= qr) return tree[id].val;    pushdown(id);    int mid = (l+r) >> 1 ;    ll res = 0;    if(ql <= mid) res |= query(id<<1,ql,qr);    if(qr > mid) res |= query(id<<1|1,ql,qr);    return res;}struct edge{    int to,next;    ll w;}s[maxn];int cnt,ti,head[maxn];int p1[maxn],p2[maxn];void add(int u,int v,ll w){    s[cnt] = (edge){v,head[u],w};    head[u] = cnt++;}void dfs_id(int u,int fa){    p1[u] = ++ti;    dfs_xx[ti] = u;    for(int i=head[u]; ~i ; i = s[i].next){        int to = s[i].to;        if(fa == to) continue;        dfs_id(to,u);    }    p2[u] = ti;}void solve(){    int n,q;    ll b[50];    scanf("%d%d",&n,&q);    for(int i=1;i<=n;i++){        ll u; scanf("%lld",&u);        b[i] = u;        a[i] = 1ll<<(u-1);    }    ti = cnt = 0; Fill(head,-1);    for(int i=1;i<=n-1;i++){        int u,v;        scanf("%d%d",&u,&v);        add(u,v,1);        add(v,u,1);    }    dfs_id(1,-1);    build(1,1,n);    while(q--){        int op; scanf("%d",&op);        if(op == 1) {            int u,v;            scanf("%d%d",&u,&v);            update(1,p1[u],p2[u],v);        }        else {            int u; scanf("%d",&u);            ll x = query(1,p1[u],p2[u]);            int cnt = 0;            while(x){                if(x&1) cnt++;                x >>= 1;            }            printf("%d\n",cnt);        }    }}