CF620E--New Year Tree(線段樹)
阿新 • • 發佈:2017-10-15
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(線段樹)