Counting Offspring

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2759    Accepted Submission(s): 956

Problem Description
You
are given a tree, it’s root is p, and the node is numbered from 1 to n.
Now define f(i) as the number of nodes whose number is less than i in
all the succeeding nodes of node i. Now we need to calculate f(i) for
any possible i.
 
Input
Multiple cases (no more than 10), for each case:
The first line contains two integers n (0<n<=10^5) and p, representing this tree has n nodes, its root is p.
Following n-1 lines, each line has two integers, representing an edge in this tree.
The input terminates with two zeros.
 
Output
For each test case, output n integer in one line representing f(1), f(2) … f(n), separated by a space.
 
Sample Input
15 7
7 10
7 1
7 9
7 3
7 4
10 14
14 2
14 13
9 11
9 6
6 5
6 8
3 15
3 12
0 0
思路:dfs序+线段树;
首先dfs序线性化,然后我们知道,如果某点是另个点的孩子节点,那么他必然在被另一个点的父亲节点所包括,所以从小到大查询[l[i],r[i]]区间的和,往线段树加点单点更新。复杂度n*log(n);
 1 #include<stdio.h>
2 #include<algorithm>
3 #include<queue>
4 #include<stdlib.h>
5 #include<iostream>
6 #include<string.h>
7 #include<set>
8 #include<map>
9 #include<vector>
10 using namespace std;
11 typedef long long LL;
12 typedef vector<int>Ve;
13 vector<Ve>vec(100005);
14 bool flag[100005];
15 int l[100005];
16 int r[100005];
17 int id[100005];
18 int cn = 0;
19 void dfs(int n);
20
21 int tree[100005*4];
22 void up(int l,int r,int k,int nn,int mm);
23 int ask(int l,int r,int k,int nn,int mm);
24 int main(void)
25 {
26 int n,p;
27 while(scanf("%d %d",&n,&p),n!=0&&p!=0)
28 { cn = 0;
29 for(int i = 0;i < 100005;i++)
30 vec[i].clear();
31 memset(flag,0,sizeof(flag));
32 for(int i = 0;i < n-1;i++)
33 {
34 int x,y;
35 scanf("%d %d",&x,&y);
36 vec[x].push_back(y);
37 vec[y].push_back(x);
38 }
39 dfs(p);
40 memset(tree,0,sizeof(tree));
41 for(int i = 1;i <= n;i++)
42 {
43 if(i == 1)
44 printf("%d",ask(l[i],r[i],0,1,cn));
45 else printf(" %d",ask(l[i],r[i],0,1,cn));
46 up(l[i],l[i],0,1,cn);
47 }
48 printf("\n");
49 }
50 return 0;
51 }
52 void dfs(int n)
53 {
54 flag[n] = true;
55 l[n] = ++cn;
56 for(int i = 0;i < vec[n].size();i++)
57 {
58 int d = vec[n][i];
59 if(!flag[d])
60 dfs(d);
61 }r[n] = cn;
62 }
63 void up(int l,int r,int k,int nn,int mm)
64 {
65 if(l > mm||r < nn)
66 {
67 return ;
68 }
69 else if(l <= nn&&r >= mm)
70 {
71 tree[k]++;return ;
72 }
73 up(l,r,2*k+1,nn,(nn+mm)/2);
74 up(l,r,2*k+2,(nn+mm)/2+1,mm);
75 tree[k] = tree[2*k+1]+tree[2*k+2];
76 }
77 int ask(int l,int r,int k,int nn,int mm)
78 {
79 if(l > mm||r < nn)
80 {
81 return 0;
82 }
83 else if(l <= nn&&r >= mm)
84 {
85 return tree[k];
86 }
87 else
88 {
89 int nx = ask(l,r,2*k+1,nn,(nn+mm)/2);
90 int ny = ask(l,r,2*k+2,(nn+mm)/2+1,mm);
91 return nx + ny;
92 }
93 }
 
Sample Output
0 0 0 0 0 1 6 0 3 1 0 0 0 2 0
 

Counting Offspring(hdu3887)的更多相关文章

  1. hdu3887 Counting Offspring

    Counting Offspring HDU - 3887 问你对于每个节点,它的子树上标号比它小的点有多少个 /* 子树的问题,dfs序可以很轻松的解决,因为点在它的子树上,所以在线段树中,必定在它 ...

  2. HDU3887 Counting Offspring [2017年6月计划 树上问题03]

    Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hdu 3887 Counting Offspring dfs序+树状数组

    Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  4. HDU 3887 Counting Offspring(DFS序+树状数组)

    Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)

    http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...

  6. HDU 3887:Counting Offspring(DFS序+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...

  7. Hdu 3887 Counting Offspring \ Poj 3321 Apple Tree \BZOJ 1103 [POI2007]大都市meg

    这几个题练习DFS序的一些应用. 问题引入: 给定一颗n(n <= 10^5)个节点的有根树,每个节点标有权值,现有如下两种操作: 1.C x y     以节点x的权值修改为y. 2.Q x ...

  8. 杭电 3887 Counting Offspring

    根据上篇翻译的文章以及很多个帖子,都讲述了树状数组最基本的功能就是tree[i]保存的是位置i左边小于等于a[i]的数的个数. 这样也就可以解释代码中为什么有f[i]=getsum(sd[i-1])- ...

  9. HDU 3887 Counting Offspring (树状数组+人工模拟栈)

    对这棵树DFS遍历一遍,同一节点入栈和出栈之间访问的节点就是这个节点的子树. 因此节点入栈时求一次 小于 i 的节点个数 和,出栈时求一次 小于 i 的节点个数 和,两次之差就是答案. PS.这题直接 ...

随机推荐

  1. ubuntu常见错误--Could not get lock /var/lib/dpkg/lock

    ubuntu常见错误--Could not get lock /var/lib/dpkg/lock   通过终端安装程序sudo apt-get install xxx时出错:   E: Could ...

  2. C#表头固定

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="info.ascx.cs& ...

  3. java四则运算规则

    java四则运算规则 1.基本规则 运算符:进行特定操作的符号.例如:+ 表达式:用运算符连起来的式子叫做表达式.例如:20 + 5.又例如:a + b 四则运算: 加:+ 减:- 乘:* 除:/ 取 ...

  4. C++中Try Catch中的继承

    1.C++中Try Catch简介:我们编译运行程序出错的时候,编译器就会抛出异常.抛出异常要比终止程序灵活许多. 而C++异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围.当程序 ...

  5. CPU 是如何认识和执行代码的

    CPU的介绍 CPU 也称为微处理器,是计算机的心脏和/或大脑. 深入研究计算机的核心,可以帮助我们有效地编写计算机程序. CPU 是计算机的心脏和大脑,它执行提供给他们的指令.它的主要工作是执行算术 ...

  6. Oracle trunc和round的区别

    1.关于trunc 和round函数比较 整体概括: round函数 四舍五入trunc函数 直接截取 对于时间: Round函数对日期进行"四舍五入",Trunc函数对日期进行截 ...

  7. 【Linux】【Shell】【Basic】流程控制

    1. 选择执行: 1.1. if 单分支的if语句: if 测试条件 then 代码分支 fi 双分支的if语句: if 测试条件; then 条件为真时执行的分支 else 条件为假时执行的分支 f ...

  8. Linux基础命令---mput上传ftp文件

    mput 使用lftp登录ftp服务器之后,可以使用put指令将文件上传到服务器.mput指令可以使用通配符,而put指令则不可以.   1.语法       mput [-c]  [-d] [-a] ...

  9. 【面试】【Linux】【Web】基础概念

    1. HTTP https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol 2. TCP handshake https://en.wikipe ...

  10. linux下把一个用户从某个组中删除,而不删除用户

    查看当前用户/登录用户 基本语法 whoami / who am I 用户组 介绍 类似于角色,系统可以对有共性的多个用户进行统一的管理. 新增组 语法 groupadd 组名 案例演示 添加test ...