【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 }

 

你可能感兴趣的:(spring)