0
点赞
收藏
分享

微信扫一扫

C++题解:苹果树

Alex富贵 2022-02-03 阅读 32

  

题目 



题解:

知识点:

树状数组

分析:

它问的是和,输入的又是树,易想到树状数组

然后呢?

我们可以对它输入的树用单链表表示,在dfs一下,利用时间戳给每个点编号。易得:编号后,一棵子树上的点的编号是连续的区间。这就可以用树状数组维护了,并解决了树状数组的更新了。

然后如何求和?【蓦淂,莞讹锝雏缇菍】我就败在这儿·······

我们要知道子树中的时间戳的最大值才可以。

核心:

void dfs(int u,int fa){
    dfn1[u]=++times;
    for (int i=h[u];~i;i=ne[i]){
        if (e[i]==fa){
            continue;
        }
        dfs(e[i],u);
    }
    dfn2[u]=times;//最大值
}

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=4e6+5,M=1e6+5;
int n,m;
int e[2*M],ne[2*M],h[M],idx;
int times,dfn1[M],dfn2[M];//dfn编号
bool vis[M];//标记该+1还是-1
int C[N];
inline void init(){
    idx=0;
    memset(h,-1,sizeof(h));
}
inline void add(int a,int b){
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void dfs(int u,int fa){
    dfn1[u]=++times;
    for (int i=h[u];~i;i=ne[i]){
        if (e[i]==fa){
            continue;
        }
        dfs(e[i],u);
    }
    dfn2[u]=times;
}
inline int lowbit(int x){
    return x&-x;
}
int getsum(int x){
    int res=0;
    for (int i=x;i>0;i-=lowbit(i)){
        res+=C[i];
    }
    return res;
}
void update(int x,int v){
    for (int i=x;i<=n;i+=lowbit(i)){
        C[i]+=v;
    }
}
int main(){
    init();
    scanf("%d%d",&n,&m);
    for (int i=0;i<n-1;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
        update(i+1,1);
    }
    update(n,1);
    dfs(1,-1);
    while (m--){
        char c;
        int x;
        scanf(" %c%d",&c,&x);
        if (c=='C'){
            update(dfn1[x],vis[x]==true ? 1 : -1);
            vis[x]^=1;
        }else{
            printf("%d\n",getsum(dfn2[x])-getsum(dfn1[x]-1));
        }
    }
    return 0;
}
举报

相关推荐

0 条评论