1. 程式人生 > 實用技巧 >CF343D. Water Tree

CF343D. Water Tree

題目連結

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;
}