• CodeForces


    New Year Tree

     CodeForces - 620E 

    给出一棵树,每个结点刚开始的时候都有一个颜色,现在有查询
    1 u col:给这个结点及其子树染上col这种颜色
    2 u:查询以u为根节点的子树的所有颜色种类

    /*
        维护子树信息,应该想到求出dfs序,在序列上维护,用线段树或者树状数组什么的搞一搞
        对于这个题: 
        遍历树一边,得出dfs序 
        建一棵线段树,每个节点维护一个long long 的val值(val分为60位分别状压60种颜色)表示当前区间是否存在某种颜色
        然后标记下传同理,然后就是线段树区间修改区间查询了
        非常要注意的是1<<i会爆,一定要写1LL<<i 
    */
    #include<iostream>
    #include<cstdio>
    #define maxn 400010
    using namespace std;
    int xu[maxn],num,head[maxn],n,p,sz[maxn],opl,opr,opv,mp[maxn],color[maxn];
    struct node{int to,pre;}e[maxn*2];
    struct Node{int l,r;long long col,lazy;}tr[maxn*16];
    void Insert(int from,int to){
        e[++num].to=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    void build(int l,int r,int k){
        tr[k].l=l;tr[k].r=r;
        if(l==r){
            int x;
            tr[k].col=(1<<color[mp[l]]-1);
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,k<<1);
        build(mid+1,r,k<<1|1);
        tr[k].col=tr[k<<1].col|tr[k<<1|1].col;
    }
    int id;
    void dfs(int now,int father){
        xu[now]=++id;mp[id]=now;
        sz[now]=1;
        for(int i=head[now];i;i=e[i].pre){
            int to=e[i].to;
            if(to==father)continue;
            dfs(to,now);
            sz[now]+=sz[to];
        }
    }
    int count(long long x){
        int res=0;
        while(x){
            res++;
            x-=(x&-x);
        }
        return res;
    }
    void update(int k){
        tr[k<<1].lazy=tr[k].lazy;
        tr[k<<1].col=tr[k].lazy;
        tr[k<<1|1].lazy=tr[k].lazy;
        tr[k<<1|1].col=tr[k].lazy;
        tr[k].lazy=0;
    }
    void change(int l,int r,int k){
        if(l>=opl&&r<=opr){
            tr[k].col=1<<opv-1;
            tr[k].lazy=1<<opv-1;
            return;
        }
        if(tr[k].lazy)update(k);
        int mid=(l+r)>>1;
        if(opl<=mid)change(l,mid,k<<1);
        if(opr>mid)change(mid+1,r,k<<1|1);
        tr[k].col=tr[k<<1].col|tr[k<<1|1].col;
    }
    long long query(int l,int r,int k){
        if(l>=opl&&r<=opr)return tr[k].col;
        if(tr[k].lazy)update(k);
        int mid=(l+r)>>1;
        long long res=0;
        if(opl<=mid)res|=query(l,mid,k<<1);
        if(opr>mid)res|=query(mid+1,r,k<<1|1);
        tr[k].col=tr[k<<1].col|tr[k<<1|1].col;
        return res;
    }
    int co(long long x){
        for(int i=1;i<=6;i++){
            if(x&(1<<i))return i;
        }
    }
    int main(){
        freopen("Cola.txt","r",stdin);
        scanf("%d%d",&n,&p);
        for(int i=1;i<=n;i++)scanf("%d",&color[i]);
        int op,x,y;
        for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            Insert(x,y);Insert(y,x);
        }
        dfs(1,0);build(1,n,1);
        for(int i=1;i<=p;i++){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d",&x,&opv);
                opl=xu[x],opr=xu[x]+sz[x]-1;
                change(1,n,1);
            }
            if(op==2){
                scanf("%d",&x);
                opl=xu[x],opr=xu[x]+sz[x]-1;
                long long w=query(1,n,1);
                printf("%d
    ",count(w));
            }
        }
    }
  • 相关阅读:
    LeetCode 224. 基本计算器 栈 双指针
    LeetCode 150. 逆波兰表达式求值 栈
    LeetCode 387. 字符串中的第一个唯一字符 哈希
    LeetCode 316. 去除重复字母 栈 哈希
    LeetCode 44. 通配符匹配 dp
    禁止屏幕旋转并同时解决以至于导致Activity重启的方法
    让振动器振动起来——Vibrator的使用
    简单的JDBC封装
    js jquery ajax 清除ie下的缓存问题
    angular.js 下拉框选中 根据后台返回值
  • 原文地址:https://www.cnblogs.com/thmyl/p/7738922.html
Copyright © 2020-2023  润新知