zoukankan      html  css  js  c++  java
  • poj 3321 Apple Tree 树状数组

    一棵树,开始时每个结点都有一个苹果,输入C x表示更新x结点,若x结点有苹果,把该结点苹果摘掉,若该节点无苹果,在该节点上增加一个新的苹果。输入Q x表示以该节点为根的子树有多少个苹果。伸手便
    该题主要问题是如何把一棵树转化为树状数组,之后便可以直接运用树状数组来求区间的和。转化的方法是用dfs深搜遍历树,每一个结点要做两次标记,第一次访问到时标记该结点,即为该结点在树状数组中的起始位置,第二次当dfs深搜返回时又一次标记,即为该结点在树状数组中末位置,始末位置之间即代表了以该结点为根的子树的所有结点。
    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    const int MAX = 100005;
     
    struct{
        int v, nxt;
    }edge[2*MAX];
    int k = 1, edgeHead[MAX];
    int n, m, dep, c[MAX];
    int low[MAX], high[MAX];
    bool pick[MAX], vis[MAX];
     
    void dfs(int u){    
        low[u] = ++ dep;   //  第一次搜到第u个节点时的深度dep,为这个节点管辖区间的上限low[i]。
        vis[u] = true;
        for(int i = edgeHead[u]; i; i = edge[i].nxt)
            if(!vis[edge[i].v])
                dfs(edge[i].v);
        high[u] = dep;     //  最后搜回来后的深度dep,为这个节点管辖区间的下限high[i]。
    }
     
    int lowbit(int x){
        return x & (-x);
    }
     
    void add(int i, int w){
        while(i <= n){
            c[i] += w;
            i += lowbit(i);
        }
    }
     
    int sum(int i){
        int ans = 0;
        while(i > 0){
            ans += c[i];
            i -= lowbit(i);
        }
        return ans;
    }
     
    int main(){
        int i, u, v, ans;
        scanf("%d", &n);
        for(i = 1; i < n; i ++){
            scanf("%d%d", &u, &v);
            edge[k].v = v;
            edge[k].nxt = edgeHead[u];
            edgeHead[u] = k ++;
        }
        for(i = 1; i <= n; i ++)
            add(i, 1);
        dep = 0;
        dfs(1);
        scanf("%d", &m);
        while(m --){
            char ord;
            getchar();
            ord=getchar();
            scanf("%d",&u);
            if(ord == 'C'){
                if(pick[u]){
                    add(low[u], 1);
                    pick[u] = false;
                }else{
                    add(low[u], -1);
                    pick[u] = true;
                }
            }else{
                ans = sum(high[u]) - sum(low[u]-1);
                printf("%d\n", ans);
            }
        }
        system("pause"); 
        return 0;
    }
  • 相关阅读:
    js 定时器 执行一次和重复执行
    Django 会议室预定
    关于跨域介绍和djiago解决跨域问题
    原生Form 和 Form组件 Modelform
    关于Djiango中 前端多对多字段点(,)的显示问题
    Djiango权限组件
    关于 or 判断都是Ture的问题
    基于多对多字段的增删改查
    二.面向对象进阶
    python大数据初探--pandas,numpy代码示例
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740244.html
Copyright © 2011-2022 走看看