杭电 3887 Counting Offspring
根据上篇翻译的文章以及很多个帖子,都讲述了树状数组最基本的功能就是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的更多相关文章
- hdu 3887 Counting Offspring dfs序+树状数组
Counting Offspring Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 3887 Counting Offspring(DFS序+树状数组)
Counting Offspring Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 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 ...
- 【DFS序+树状数组】HDU 3887 Counting Offspring
http://acm.hdu.edu.cn/showproblem.php?pid=3887 [题意] 给定一棵树,给定这棵树的根 对于每个结点,统计子树中编号比他小的结点个数 编号从小到大一次输出 ...
- HDU 3887 Counting Offspring (树状数组+人工模拟栈)
对这棵树DFS遍历一遍,同一节点入栈和出栈之间访问的节点就是这个节点的子树. 因此节点入栈时求一次 小于 i 的节点个数 和,出栈时求一次 小于 i 的节点个数 和,两次之差就是答案. PS.这题直接 ...
- hdu 3887 Counting Offspring(DFS序【非递归】+树状数组)
题意: N个点形成一棵树.给出根结点P还有树结构的信息. 输出每个点的F[i].F[i]:以i为根的所有子结点中编号比i小的数的个数. 0<n<=10^5 思路: 方法一:直接DFS,进入 ...
- 杭电ACM分类
杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze ...
- hdu3887 Counting Offspring
Counting Offspring HDU - 3887 问你对于每个节点,它的子树上标号比它小的点有多少个 /* 子树的问题,dfs序可以很轻松的解决,因为点在它的子树上,所以在线段树中,必定在它 ...
- acm入门 杭电1001题 有关溢出的考虑
最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...
随机推荐
- 简单的Dao设计模式
简单的DAO设计模式 这两天学习到了DAO(Data Access Object 数据存取对象)设计模式.想谈谈自己的感受,刚开始接触是感觉有点难,觉得自己逻辑理不清,主要是以前学的知识比较零散没有很 ...
- 盒子模型&position定位
有时候深深的感觉语文这门课程其实很有用, 至少以前学的时候没有感觉到 直到现在阅读大量的别人的资料文章的时候或者是看一些题目....... 总之:认真阅读小心品味 当然,前面的孤言自语和本文无关,只是 ...
- 多校联赛2 Problem2 Warm up 求桥的数目+缩点后的树的直径 当时被不知道原因的爆栈爆到无语了。。
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total S ...
- jQuery Pagination Ajax分页插件中文详解(摘)
jQuery Pagination Ajax分页插件中文详解 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxin ...
- 关于使用STL常见的两个bug
1.bug 1 class CTest { public : vector<int> getVector() const //需要写成引用形式,不然下面begin.end调用会以拷贝形式调 ...
- [Git] --no-verify
Somtimes, the project might set the commit message guide line, if your commit doesn't meet the requi ...
- 如何在编译内核时添加缺少的固件(随着intel wireless 5100 AGN的 iwlwifi 案例)
我不知道你在笔记本使用 Linux 在内核编译无线wifi 不能用.我的书"关联 Y450"一个足够的旧书,随着无线网卡: $ lspci | grep Wireless 06:0 ...
- jsp当参数为空的时候默认显示值
当${business.branchName }为空或者不存在的时候显示“请选择门店” <c:out value="${business.branchName }" defa ...
- [core java学习笔记][第六章接口与内部类]
接口域内部类 接口 描述类具有什么功能,不给出具体实现. 内部类 用于设计协作关系的类集合 代理 实现任意接口的对象. 6.1 接口 接口声明 public interface Comparable ...
- table-cell完成左侧定宽,右侧定宽及左右定宽等布局
使用table-cell完成以下几种布局(ie8及以上兼容) 1.左侧定宽-右侧自适应 .left{ width: 300px; height: 500px; border: 1px solid; f ...