根据上篇翻译的文章以及很多个帖子,都讲述了树状数组最基本的功能就是tree[i]保存的是位置i左边小于等于a[i]的数的个数.

这样也就可以解释代码中为什么有f[i]=getsum(sd[i-1])-getsum(st[i]))/2。因为getsum保存的就是左边比i小的数,注意因为序列是通过dfs求出的,因而每个节点都有进入和退出过程,也就是每个节点都出现了2次,比如说对于数4来说,有4个节点,假设3为顶点,边的关系是3-2-1,3-2-4,那么dfs扫描出的序列就是3,2,1,1,4,4,2,3.所以求出的最终结果就需要除以2,因为每个数字都出现了2次。

至于为什么是从n-->1,我也纠结了半天,后来总算是YY出了一点思路【也可能不对】,因为已经将tree初始过了,考虑最原始的BIT,我们是一边遍历原始数组,一边getsum,一边update树,更新时,tree[i]+=1,这里提前将tree update过了,那么只能从后向前走,update(-1)了。假定最后一个点是n,那么在考虑其他节点的时候是不需要考虑这个点的,因为任何一个点都比最后这个点小,所以。。。update的时候是(-1)。

代码中注释的部分是原作者的,为了证实一下我自己YY出的结果是否正确,我测试了一下,果然A掉了。所以我的想法应该是对的,如果从头开始的话,需要从头遍历数组,得结果的时候需要两次update(1),这样的话仅仅需要从1-->就可以了。

代码如下:

#pragma comment(linker,"/STACK:100000000,100000000")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std; const int maxn=100005;
vector<int>vt[maxn];
int bit[2*maxn];
int que[2*maxn];
int st[maxn];
int sd[maxn];
int f[maxn];
int n, rt, num; void dfs(int u, int fa)
{
que[++num]=u;
for(int i=0; i<vt[u].size(); i++)
{
int v=vt[u][i];
if(v==fa) continue;
dfs(v,u);
}
que[++num]=u;
} int lowbit(int x)
{
return x&(-x);
} void update(int x, int val)
{
while(x<=num)
{
bit[x]+=val;
x+=lowbit(x);
}
} int getsum(int x)
{
int ans=0;
while(x>0)
{
ans+=bit[x];
x-=lowbit(x);
}
return ans;
} int main()
{
//int a=4,b=3;
//printf("%d",a|b);
while(~scanf("%d%d",&n,&rt),n+rt)
{
for(int i=0; i<=n; i++)
vt[i].clear();
for(int i=1; i<n; i++)
{
int x, y;
scanf("%d%d",&x,&y);
vt[x].push_back(y);
vt[y].push_back(x);
}
fill(st+1,st+1+n,0);
num=0;
dfs(rt,-1);
//每个节点开始和结束的位置
for(int i=1; i<=num; i++)
{
if(!st[que[i]])
st[que[i]]=i;
else
sd[que[i]]=i;
}
memset(bit,0,sizeof(bit));
/*
for(int i=1; i<=num; i++)
update(i,1);
for(int i=n; i>=1; i--)
{
f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;
update(st[i],-1);
update(sd[i],-1);
}*/
for(int i=1;i<=n;i++)//这里是测试从1-->n的,注意对比
{
update(st[i],1);
update(sd[i],1);
f[i]=(getsum(sd[i]-1)-getsum(st[i]))/2;
}
printf("%d",f[1]);
for(int i=2; i<=n; i++)
printf(" %d",f[i]);
puts("");
}
return 0;
}

杭电 3887 Counting Offspring的更多相关文章

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

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

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

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

  3. 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 ...

  4. 【DFS序+树状数组】HDU 3887 Counting Offspring

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 [题意] 给定一棵树,给定这棵树的根 对于每个结点,统计子树中编号比他小的结点个数 编号从小到大一次输出 ...

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

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

  6. hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)

    题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...

  7. 杭电ACM分类

    杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...

  8. hdu3887 Counting Offspring

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

  9. acm入门 杭电1001题 有关溢出的考虑

    最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...

随机推荐

  1. Java连接Oracle数据库的示例代码

    最基本的Oracle数据库连接代码(只针对Oracle11g): 1.右键项目->构建路径 ->配置构建路径,选择第三项“库”,然后点击“添加外部Jar”,选择 “D:\Oracle\ap ...

  2. Hopscotch(细节)

     Hopscotch Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit  ...

  3. H Language Blueprint

    H Language Blueprint I will design the H language in the very-soon future, it will be like: 1- a scr ...

  4. springMVC3学习(六)--SimpleFormController

    SimpleFormController提交表单流程例如以下: login.jsp <form action="login" method="post"& ...

  5. 大到可以小说的Y组合子(二)

    问:上一回,你在最后曾提到"抽象性不足",这话怎么说? 答:试想,如果现在需要实现一个其它的递归(比如:Fibonacci),就必须把之前的模式从头套一遍,然后通过fib_make ...

  6. Could not load file or assembly 试图加载格式不正确的程序

    问题: 今天发布项目的时候遇到这个破问题,纳闷了好久,最后想起来自己改过程序生成的目标平台(原生成目标平台是Any CPU,被我改成了X86的). 解决方法: 改回原来的Any CPU 从新发布即可.

  7. Android Service(下)

    转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...

  8. Win8.1系统下安装nodeJS

    Nodejs简介 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.js ...

  9. CDZSC_2015寒假新人(2)——数学 C

    C - C Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status ...

  10. c++连接mysql数据库(使用mysql api方式,环境VS2013+MYSQL5.6)

    转载请注明出处,原文地址http://www.cnblogs.com/zenki-kong/p/4382657.html 刚开始写博客,博主还只是个大三汪,学艺不精,如有错误还请前辈指出(>^ω ...