1. 程式人生 > >CF620E--New Year Tree(線段樹)

CF620E--New Year Tree(線段樹)

bug get esp lag bits ongl 結構 log 進制

CodeForces - 620E

1.題意

    對於一棵樹進行以下兩種操作:

1 v c 將根為v的子樹全部染色為c

     2 v 查詢根為v的子樹的顏色的個數

2.思路

    首先利用dfs時間序將樹轉化為線性結構,然後利用線段樹進行區間顏色數的處理,然後因為只有60種顏色,那麽我們可以用一個long long 值來保存一個去區間顏色數(也就是對於顏色i,那麽對應的longlong值的二進制位為1,一個區間的顏色數也就是區間值的二進制的1的個數),然後區間合並則直接對兩個區間的值進行或運算(|);

    需要註意的是移位時防止溢出.

3.代碼

#define debug printf("%s: %d\n", __FUNCTION__, __LINE__);

#include <bits/stdc++.h>
using namespace std;
const int N = 4e5+5;
typedef long long ll;
#define ls rt<<1
#define rs rt<<1|1

// 二進制記錄數居

struct Edge{
    int to, next;
};

int head[N];
Edge e[N<<1];
int tot;

void addEdge(int u, int v) {
    e[++ tot] = Edge{u, head[v]};
    head[v] = tot;
    e[++ tot] = Edge{v, head[u]};
    head[u] = tot;
}

int l[N], r[N];
int dfs_clock;
int pos[N];

// dfs將樹轉化為線性結構
void dfs(int u, int fa) {
    l[u] = ++ dfs_clock;
    pos[dfs_clock] = u;
    for(int i = head[u]; i; i = e[i].next) {
        int to = e[i].to;
        if(to == fa) continue;
        dfs(to, u);
    }
    r[u] = dfs_clock;    
}

int c[N];
ll v[N<<2];
int flag[N<<2];

inline void pushUp(int rt) {
    v[rt] = v[ls]|v[rs];
}

void pushDown(int rt) {
    if(flag[rt]) {
        flag[ls] = flag[rs] = flag[rt];
        v[ls] = (1ll<<flag[rt]);
        v[rs] = (1ll<<flag[rt]);   // 註意防止溢出
        flag[rt] = 0;
    }
}

void build(int rt, int l, int r) {
    if(l == r) {
        v[rt] = (1ll<<c[pos[l]]);
        return ;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid);
    build(rs, mid+1, r); 
    pushUp(rt);
}

void update(int rt, int l, int r, int a, int b, int ci) {
    if(a <= l && r <= b) {
        flag[rt] = ci;
        v[rt] = (1ll<<ci);
        return ;
    } 
    pushDown(rt);
    int mid = (l + r) >> 1;
    if(a <= mid) {
        update(ls, l, mid, a, b, ci);
    }
    if(b > mid) {
        update(rs, mid+1, r, a, b, ci);
    }
    pushUp(rt);
}

ll query(int rt, int l, int r, int a, int b) {
    if(a <= l && r <= b) {
        return v[rt];
    } 
    pushDown(rt);
    ll res = 0;
    int mid = (l + r) >> 1;
    if(a <= mid) {
        res |= query(ls, l, mid, a, b);
    }
    if(b > mid) {
        res |= query(rs, mid+1, r, a, b);
    }
    pushUp(rt);
    return res;
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++ i) {
        scanf("%d", &c[i]);
    }     
    for(int i = 1; i < n; ++ i) {
        int x, y;
        scanf("%d%d", &x, &y);
        addEdge(x, y);
    }

    dfs(1, 0);
    build(1, 1, n);

    while(m --) {
        int k;
        scanf("%d", &k);
        if(k == 1) {
            int x, y;
            scanf("%d%d", &x, &y);
            update(1, 1, n, l[x], r[x], y);  
        }
        else {
            int x;
            scanf("%d", &x);
            ll res = query(1, 1, n, l[x], r[x]);
            int s = 0;
            while(res) {
                s += res&1;
                res >>= 1;
            }
            printf("%d\n", s);
        }
    }
    return 0;
}

CF620E--New Year Tree(線段樹)