zoukankan      html  css  js  c++  java
  • POJ 3321 Apple Tree DFS序 + 树状数组

    多次修改一棵树节点的值,或者询问当前这个节点的子树所有节点权值总和。

    首先预处理出DFS序L[i]和R[i]

    把问题转化为区间查询总和问题。单点修改,区间查询,树状数组即可。

    注意修改的时候也要按照dfs序修改,因为你查询就是按照dfs查的,所以修改也要用dfs序修改

    L[i]是唯一的。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 100000 + 20;
    int first[maxn], L[maxn], R[maxn], a[maxn];
    struct edge {
        int u, v;
        int next;
    } e[maxn * 2];
    int n, num;
    void add (int u, int v)
    {
        ++num;
        e[num].u = u;
        e[num].v = v;
        e[num].next = first[u];
        first[u] = num;
    }
    bool book[maxn];
    int index;
    void dfs (int cur)
    {
        L[cur] = index;
        for (int i = first[cur]; i; i = e[i].next) {
            if (book[e[i].v] == 0) {
                book[e[i].v] = 1;
                index++;
                dfs (e[i].v);
            }
        }
        R[cur] = index;
    }
    int c[maxn];//树状数组,多case的记得要清空
    int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num
    {
        return x&(-x);
    }
    void addc (int pos,int val)//在第pos位加上val这个值
    {
        while (pos<=n) { //n是元素的个数
            c[pos] += val;
            pos += lowbit(pos);
        }
        return ;
    }
    int get_sum (int pos) //求解:1--pos的总和
    {
        int ans = 0;
        while (pos) {
            ans += c[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    void work ()
    {
        for (int i = 1; i <= n - 1; ++i) {
            int u, v;
            scanf ("%d%d", &u, &v);
            add (u, v);
        }
        for (int i = 1; i <= n; ++i) {
            addc (i, 1);
            a[i] = 1;
        }
        dfs (1);
        int m;
        scanf ("%d", &m);
        for (int i = 1; i <= m; ++i) {
            char str[3];
            int id;
            scanf ("%s%d", str, &id);
            if (str[0] == 'Q') {
                printf ("%d
    ", get_sum (R[id]) - get_sum (L[id] - 1));
            } else {
                id = L[id]; //查询用dfs序查,那么更改也要用dfs序更改
                a[id] = -a[id];
                addc (id, a[id]);
            }
        }
        return ;
    }
    int main ()
    {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        while (~scanf ("%d", &n)) {
            index = 1;
            work ();
            memset (first, 0, sizeof first);
            num = 0;
            memset (book, 0, sizeof book);
            memset (c, 0, sizeof c);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SpringCloud笔记(一)服务注册与发现
    个人备忘录
    ActiveMQ 消息持久化到Mysql数据库
    染色 [组合数 容斥]
    各种图床
    NOIP2012 疫情控制
    网格计数
    找钱 [多重背包 计数]
    序列[势能线段树]
    牛客挑战赛33 B-鸽天的放鸽序列
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5828021.html
Copyright © 2011-2022 走看看