CF343D. Water Tree
阿新 • • 發佈:2020-11-19
題目連結
https://codeforces.com/contest/343/problem/D
題意
給出一棵以 \(1\) 為根節點的 \(n\) 個節點的有根樹。每個點有一個權值,初始為 \(0\)。
\(m\) 次操作。操作有 \(3\) 種:
1.將點 \(u\) 和其子樹上的所有節點的權值改為 \(1\)。
2.將點 \(u\) 到 \(1\) 的路徑上的所有節點的權值改為 \(0\)。
3.詢問點 \(u\) 的權值。
思路
利用DFS序建樹, 對於操作1就是簡單的區間更新。
操作2在DFS序上是離散的, 不能直接暴力更新,
換個思路,我們可以只更新這個點。
容易想到每次1操作填滿子樹, 假如一個點當前為1,那麼它的所有子樹必定都是1, 如果子樹某個節點的權值為0, 那麼2操作必定把這個節點的祖先都更新了。
那麼操作三隻需要查詢該點以及其子樹是否都為1即可。
注意操作1時,若u的子樹中有0,必須把u的父親更新成0。
AC程式碼
#include<bits/stdc++.h> #define ls rt << 1 #define rs rt << 1 | 1 #define lson l , mid , rt << 1 #define rson mid + 1, r, rt << 1 | 1 #define lr2 (l + r) >> 1 using namespace std; typedef long long ll; const int maxn = 5e5 + 50; int sum[maxn << 2], lazy[maxn << 2]; int a[maxn]; void push_up(int rt){ sum[rt] = sum[ls] & sum[rs]; } void push_down(int rt){ if(lazy[rt]){ sum[ls] = 1; sum[rs] = 1; lazy[ls] = 1; lazy[rs] = 1; lazy[rt] = 0; } } void update(int a, int b, int l, int r, int rt){ if(a <= l && b >= r){ lazy[rt] = 1; sum[rt] = 1; return; } push_down(rt); int mid = lr2; if(a <= mid) update(a, b, lson); if(b > mid) update(a, b, rson); push_up(rt); } void insert(int pos, int val, int l, int r, int rt){ if(l == r){ lazy[rt] = 0; sum[rt] = val; return; } push_down(rt); int mid = lr2; if(pos <= mid) insert(pos, val, lson); else insert(pos, val, rson); push_up(rt); } int query(int a, int b, int l, int r, int rt){ if(a <= l && b >= r){ return sum[rt]; } int mid = lr2; push_down(rt); int ans = 1; if(a <= mid) ans &= query(a, b, lson); if(b > mid) ans &= query(a, b, rson); push_up(rt); return ans; } int cnt, n; vector<int> G[maxn]; int L[maxn], R[maxn]; int far[maxn]; void dfs(int v, int fa){ far[v] = fa; L[v] = ++cnt; for(auto u : G[v]){ if(u != fa){ dfs(u, v); } } R[v] = cnt; } int main() { std::ios::sync_with_stdio(false); cin >> n; for(int i = 2;i <= n;i++){ int x, y;cin >> x >> y; G[x].push_back(y); G[y].push_back(x); } dfs(1, -1); int q; cin >> q; while(q--){ int op, x; cin >> op >> x; if(op == 1){ if(!query(L[x], R[x], 1, n , 1)) insert(L[far[x]], 0, 1, n , 1); update(L[x], R[x], 1, n , 1); } else if(op == 2) insert(L[x], 0, 1, n , 1); else { cout << query(L[x], R[x], 1, n, 1) << endl; } } return 0; }