POJ 3321 - Apple Tree DFS出时间搓,树状数组统计维护..

来源:互联网 发布:linux iostat命令详解 编辑:程序博客网 时间:2024/05/06 03:48

             题意:

                      有一颗苹果树..初始时所有枝条上面的苹果树为1...现在做操作..C x代表若x有苹果摘掉..若x无苹果加上..然后Q x代表询问以x个根的子树共有多少个苹果..

             题解:

                      用dfs求出时间搓(类似后续遍历)....标记出每个点位根子树的左右界..然后就是单点更新区间求和了...线段树主要是会超时..树状数组解决..


Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<queue>#include<stack>#include<algorithm>#include<cmath>#include<set>#include<map>#define ll long long#define oo 1<<29#define MAXN 500005#define pi acos(-1.0)#define esp 1e-30using namespace std;   struct node{       int v,next; }edge[MAXN];int ne,_next[MAXN];int n,id,sum[MAXN],h[MAXN],L[MAXN],R[MAXN]; void addedge(int u,int v){       edge[++ne].next=_next[u];       _next[u]=ne,edge[ne].v=v;}void dfs(int x){       L[x]=++id;       for (int k=_next[x];k;k=edge[k].next)          if (!L[edge[k].v]) dfs(edge[k].v);        R[x]=id;       return;}void Insert(int k,int x){        while (k<=n)       {              sum[k]+=x;              k+=k&(-k);       }}int Query(int k){         int ans=0;       while (k)       {              ans+=sum[k];              k-=k&(-k);       }       return ans;}int main(){          int Q,i,u,v;       char c;         scanf("%d",&n);       ne=0,memset(_next,0,sizeof(_next));       for (i=1;i<n;i++)       {                scanf("%d%d",&u,&v);                addedge(u,v),addedge(v,u);        }       id=0;        memset(L,0,sizeof(L));       dfs(1);       memset(sum,0,sizeof(sum));       for (i=1;i<=n;i++) h[i]=1,Insert(L[i],1);       scanf("%d",&Q);       while (Q--)       {                do { c=getchar(); } while (c!='Q' && c!='C');                scanf("%d",&i);                if (c=='C')                 {                       if (h[i]) Insert(L[i],-1);                            else Insert(L[i],1);                       h[i]=1-h[i];                                            }else                         printf("%d\n",Query(R[i])-Query(L[i]-1));       }               return 0;}


原创粉丝点击