• 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;
    }
    
    
  • 相关阅读:
    Codeforces Round #183 (Div. 2) B. Calendar
    FZU Problem 2030 括号问题
    NEU(1262: ASCII Sequence II)动态规划
    ZOJ(1711)Sum It Up (DFS+剪枝+去重复)
    ZOJ(1004)Anagrams by Stack (DFS+stack)
    HDU(3374) (KMP + 最小表示法)
    FZU Problem 1926 填空(KMP好题一枚,确实好)
    POJ(2481)Cows 树状数组
    HOJ (1042) 整数划分
    LeetCode: Two Sum
  • 原文地址:https://www.cnblogs.com/Carered/p/14007998.html
Copyright © 2020-2023  润新知