POJ 3321Apple Tree(dfs序 树状数组)

传送门:http://poj.org/problem?id=3321
刚开始看到这题的时候,直接敲了一发模拟准备水过,结果TLE了,仔细想想确实是会超时的,如果变成一条直线的话,修改操作的复杂度就是O(N),妥妥超时。想了半天不知道怎么做,后来一查发现是树状数组,一时间没想出来怎么做,因为原来做的树状数组都是一条直线上操作,不知道怎么在树上建立树状数组。学习了一发别人的博客,才知道还有一种思路是根据树的dfs序来建立树状数组,先dfs一下,然后在dfs的时候编号。那么一个节点和他的全部子树的编号一定是连续的。所以这段连续区间就可以用来表示这个节点和他的子树。第一次看到这种做法,感觉非常吊炸天。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define PB push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define calm (l+r)>>1
const int INF=1e9+7;

const int maxn=100100;
struct EE{
    int to,next;
    EE(){}
    EE(int to,int next):to(to),next(next){}
}edge[maxn];
int n,m,head[maxn],Ecnt,vis;
int st[maxn],ed[maxn],v[maxn];
int tree[maxn]={0};
inline void add(int s,int t){
    edge[Ecnt]=EE(t,head[s]);
    head[s]=Ecnt++;
}
void update(int x,int v){
    while(x<=n){
        tree[x]+=v;
        x+=x&(-x);
    }
}
int sum(int x){
    int ans=0;
    while(x){
        ans+=tree[x];
        x-=x&(-x);
    }
    return ans;
}
void build(int s){
    st[s]=++vis;//st[s]表示当前这个节点
    for(int i=head[s];~i;i=edge[i].next){
        build(edge[i].to);
    }
    ed[s]=vis;//ed[x]表示它的所有子树的编号的最后一个,st[s]--ed[s]这段区间就可以表示这个节点与它的所有子树
}
int main(){
    #ifdef LOCAL
        freopen("input.txt","r",stdin);
    #endif
    scanf("%d",&n);
    memset(head,-1,sizeof head);Ecnt=0;
    for(int i=1;i<n;i++){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);
    }
    vis=0;
    build(1);
    for(int i=1;i<=n;i++){
        v[i]=1;update(st[i],1);
        //printf("%d %d\n",st[i],ed[i]);
    }
    scanf("%d",&m);
    while(m--){
        char op[2];
        scanf("%s",op);
        if(op[0]=='Q'){
            int x;scanf("%d",&x);
            printf("%d\n",sum(ed[x])-sum(st[x]-1));
        }
        else{
            int x;scanf("%d",&x);
            if(v[x]==1){    
                update(st[x],-1);
            }
            else{
                update(st[x],1);
            }
            v[x]=1-v[x];
        }
    }
    #ifdef LOCAL
        printf("[Run in %.1fs]\n",(double)clock()/CLOCKS_PER_SEC);
    #endif
    return 0;
}

你可能感兴趣的:(POJ 3321Apple Tree(dfs序 树状数组))