zoukankan      html  css  js  c++  java
  • POJ_3321_APPLE_TREE

    poj上面的一道求子树上苹果的题目,网上看了很多题解,下面我来回忆一下,基本来源于大神的微博,http://blog.csdn.net/zhang20072844,我来做个搬运工。
    先将树的n条边上节点重新标号,让每一棵子树上的节点编号构成一个连续的区间,然后利用dfs将第i个节点表示的区间下限,上限存进数组low[u],high[u]。树状数组c[i]=a[i-2^k+1]+a[i-2^k+2]+.....a[i],也就是i-2^k+1到i之间的苹果总数,每一个a[i]表示树上一个分叉,i是经过重新标号后的表示节点的值。可以通过add(low[i],1)为第i(原苹果树中标号)个节点增加一个苹果,同时更新树状数组中和i(也就是元素a[low[i]]有关的c[j]值,这样查询low[i]到high[i]区间范围内的苹果数目便可以通过sum(high[i])-sum(low[i]-1),其中sum(t)表示a[i]+a[2].....a[t]之和也就是这些节点上苹果数目。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define N 100010
     4 
     5 typedef struct
     6 {
     7     int to,next;
     8 } Edge;
     9 Edge edge[N];
    10 int low[N],high[N],vis[N],c[N*2],head[N],pick[N];
    11 int dep,p,n;
    12 
    13 void addedge(int cu,int cv)
    14 {
    15     edge[p].to=cv;
    16     edge[p].next=head[cu];
    17     head[cu]=p++;
    18 }
    19 
    20 void dfs(int u)
    21 {
    22     low[u]=++dep;
    23     vis[u]=1;
    24     int i;
    25     for(i=head[u]; i!=-1; i=edge[i].next)
    26     {
    27         if(!vis[edge[i].to])
    28             dfs(edge[i].to);
    29     }
    30     high[u]=dep;
    31 }
    32 
    33 int lowbit(int x)
    34 {
    35     return x&(-x);
    36 }
    37 void add(int t,int v)
    38 {
    39     while(t<=n)
    40     {
    41         c[t]+=v;
    42         t+=lowbit(t);
    43     }
    44 }
    45 
    46 int sum(int t)
    47 {
    48     int res=0;
    49     while(t>0)
    50     {
    51         res+=c[t];
    52         t-=lowbit(t);
    53     }
    54     return res;
    55 }
    56 
    57 int main(void)
    58 {
    59     int m,i,u,v;
    60     memset(head,-1,sizeof(head));
    61     scanf("%d",&n);
    62     for(i=1; i<n; i++)
    63     {
    64         scanf("%d%d",&u,&v);
    65         addedge(u,v);
    66     }
    67     dfs(1);
    68     for(i=1; i<=n; i++)
    69     {
    70         add(i,1);
    71         pick[i]=1;
    72     }
    73     scanf("%d",&m);
    74     while(m--)
    75     {
    76         getchar();
    77         char op;
    78         scanf("%c%d",&op,&i);
    79         if(op=='Q')
    80             printf("%d
    ",sum(high[i])-sum(low[i]-1));
    81         else
    82         {
    83             if(pick[i])
    84             {
    85                 add(low[i],-1);
    86                 pick[i]=0;
    87             }
    88             else
    89             {
    90                 add(low[i],1);
    91                 pick[i]=1;
    92             }
    93         }
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    vector读入指定行数但不指定列数的数字
    p4语言编程环境安装
    近期学习资料一览表
    c++之洛谷P1068分数线划定
    打开文件的方法
    调用当前年月日
    想学习启发式优化算法,不知从何学起?
    使用这几款插件,能让你在GitHub看代码的效率翻倍
    微信公众号放Latex数学公式的完美解决方案
    手把手教你用Git备份保存论文和代码等重要数据到云端
  • 原文地址:https://www.cnblogs.com/rootial/p/3207752.html
Copyright © 2011-2022 走看看