zoukankan      html  css  js  c++  java
  • 【HDU 3887 Counting Offspring】 dfs序+树状数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3887

    题目大意: 给你一颗n个节点的数,对于每个节点i,问你每个节点的子树中有多少个节点序列数小于i,求f[i]。

    解题思路:

       用样例来说明,我们可以先深搜一遍,那么深搜得到的序列就是  7,3,15,15,12, 12, 3, 4, 4, 1, 1, 10, 14, 13, 13, 2, 2, 14, 10,……9, 7

       对这个序列进行分析可以发现,举例:3,15,15,12, 12, 3 , 节点3中间的数就是它的子树序列。

      dfs打好序列后就对序列进行遍历一遍,开两个st[], sd[] 数组, 存每个节点开始和结束位置。接下来就是树状数组求和,注意这里要序列从大到小求和(也就是n-->1),求完后删掉对应位置的数,树状数组进行相应的更新操作。

     1 #pragma comment(linker, "/STACK:1024000000,1024000000")
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <cstring>
     7 using namespace std;
     8 
     9 const int maxn=100005;
    10 vector<int>vt[maxn];
    11 int bit[2*maxn];
    12 int que[2*maxn];
    13 int st[maxn];
    14 int sd[maxn];
    15 int f[maxn];
    16 int n, rt, num;
    17 
    18 void dfs(int u, int fa)
    19 {
    20     que[++num]=u;
    21     for(int i=0; i<vt[u].size(); i++)
    22     {
    23         int v=vt[u][i];
    24         if(v==fa) continue;
    25         dfs(v,u);
    26     }
    27     que[++num]=u;
    28 }
    29 
    30 int lowbit(int x)
    31 {
    32     return x&(-x);
    33 }
    34 
    35 void cal(int x, int val)
    36 {
    37     while(x<=num)
    38     {
    39         bit[x]+=val;
    40         x+=lowbit(x);
    41     }
    42 }
    43 
    44 int getsum(int x)
    45 {
    46     int ans=0;
    47     while(x>0)
    48     {
    49         ans+=bit[x];
    50         x-=lowbit(x);
    51     }
    52     return ans;
    53 }
    54 
    55 int main()
    56 {
    57     while(~scanf("%d%d",&n,&rt),n+rt)
    58     {
    59         for(int i=0; i<=n; i++)
    60             vt[i].clear();
    61         for(int i=1; i<n; i++)
    62         {
    63             int x, y;
    64             scanf("%d%d",&x,&y);
    65             vt[x].push_back(y);
    66             vt[y].push_back(x);
    67         }
    68         fill(st+1,st+1+n,0);
    69         num=0;
    70         dfs(rt,-1);
    71         for(int i=1; i<=num; i++)
    72         {
    73             if(!st[que[i]]) st[que[i]]=i;
    74             else sd[que[i]]=i;
    75         }
    76         memset(bit,0,sizeof(bit));
    77         for(int i=1; i<=num; i++)
    78             cal(i,1);
    79         for(int i=n; i>=1; i--)
    80         {
    81             f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;
    82             cal(st[i],-1);
    83             cal(sd[i],-1);
    84         }
    85         printf("%d",f[1]);
    86         for(int i=2; i<=n; i++)
    87             printf(" %d",f[i]);
    88         puts("");
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    web应用程序的状态管理
    web学习笔记二
    java Web 学习笔记一
    简述Bootstrap栅格布局方式
    CSS3笔记
    CSS 笔记
    初识HTML流水笔记
    数据库初识
    java流的操作
    Java 套接字使用
  • 原文地址:https://www.cnblogs.com/kane0526/p/2855125.html
Copyright © 2011-2022 走看看