CodeForce 343D. 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;
}

posted @ 2020-11-19 21:14  Carered  阅读(125)  评论(0编辑  收藏  举报