POJ3321Apple Tree Dfs序 树状数组

出自——博客园-zhouzhendong

~去博客园看该题解~

题目

POJ3321 Apple Tree

 

题意概括

有一颗01树,以结点1为树根,一开始所有的结点权值都是1,有两种操作:

  1.改变其中一个结点的权值(0变1,1变0)

  2.询问子树X的节点权值和。

 

输入描述

一组数据。

先是一个数n,表示有n个节点。

接下去n-1行,每行表示一条边。

然后一个数m,表示有m个操作。

然后m行,每行一个字母一个数x,如果字母是Q,则是询问;否则是修改。

 

输出描述

每一个询问一行,表示答案。

 

题解

 

直接把题目变成dfs序上单点修改和区间sum询问的问题。

单点修改,不用线段树,树状数组就可以了。

如果你非要用线段树我也不拦你……

 

代码

 

#pragma comment(linker,"/STACK:1024000000,1024000000") 
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=100000+5,M=N*2;
struct Edge{
    int cnt,y[M],nxt[M],fst[N];
    void set(){
        cnt=0;
        memset(fst,0,sizeof fst);
    }
    void add(int a,int b){
        y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    }
}e;
int n,m;
int in[N],out[N],time;
int tree[N],v[N];//树状数组 
int lowbit(int x){
    return x&-x;
}
void dfs(int prev,int rt){
    in[rt]=++time;
    for (int i=e.fst[rt];i;i=e.nxt[i])
        if (e.y[i]!=prev)
            dfs(rt,e.y[i]);
    out[rt]=time;
}
void update(int x,int d){
    for (;x<=n;x+=lowbit(x))
        tree[x]+=d;
}
int sum(int x){
    int ans=0;
    for (;x>0;x-=lowbit(x))
        ans+=tree[x];
    return ans;
}
int query(int L,int R){
    return sum(R)-sum(L-1);
}
int main(){
    e.set();
    scanf("%d",&n);
    for (int i=1,a,b;i<n;i++){
        scanf("%d%d",&a,&b);
        e.add(a,b);
        e.add(b,a);
    }
    time=0;
    dfs(0,1);
    for (int i=1;i<=n;i++)
        tree[i]=lowbit(i),v[i]=1;
    scanf("%d",&m);
    for (int i=1,x;i<=m;i++){
        char ch[2];
        scanf("%s%d",ch,&x);
        if (ch[0]=='Q')
            printf("%d
",query(in[x],out[x]));
        else
            update(in[x],1-v[x]*2),v[x]^=1;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhouzhendong/p/POJ3321.html