2014 csu校赛 I 题,比赛的时候拿着他看了几个小时愣是没弄出好的方法,我们也想过统计出每个root的节点总数,然后减去离它d层的子节点的数目,即为答案。但是因为树的存储是无序的,所以每次为了找到子节点还是需要搜索,这肯定是承受不了的。

事实上,这个思路大体是对的,只是需要进行预处理,使得在找离它为d层的子节点能尽量节约时间,此外,如果找到了子节点挨个去减,也是很费时的,因为这些子节点必定处在同一层,他们的bfs序是连续的,故比较容易想到用前缀和来快速求得某一层的所有儿子的数目。

我们看这样的树

因此我们如果能把每个root的dfs时间戳的最小值和最大值给记录一下,再求出bfs序,则,对于某一层的所有节点,只要是时间戳在该root的最小值和最大值范围内,则必定是我们要求得孩子节点。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define N 100010
using namespace std;
vector <int> deep_num[N];
int u[N],v[N],nt[N],ft[N],cnt,dfs_clock;
int last[N][],max_deep[N],tot[N],deep[N],sum[N];
void add(int a,int b){
u[cnt]=a;
v[cnt]=b;
nt[cnt]=ft[a];
ft[a]=cnt++;
}
void init(int num)
{
cnt=;
dfs_clock=;
sum[]=; for (int i=;i<=num;i++){
ft[i]=-;
nt[i]=;
u[i]=v[i]=;
deep_num[i].clear();
deep_num[i].push_back(); //先给每个层预先加一个0,方便之后处理
}
}
void dfs(int u,int d)
{
last[u][]=++dfs_clock;
deep_num[d].push_back(u);//这里直接把节点存入相应的层,省去了BFS,直接达到了计算BFS序的作用
tot[u]=;
deep[u]=d;
max_deep[u]=d;
for (int w=ft[u];w>=;w=nt[w]){
int x=v[w];
dfs(x,d+);
tot[u]+=tot[x];//计算root节点下的节点总数
max_deep[u]=max(max_deep[u],max_deep[x]);//记录该root最大层有多深
}
last[u][]=dfs_clock;
if (deep_num[deep[u]].size()>)
sum[u]=sum[deep_num[deep[u]][deep_num[deep[u]].size()-]]+tot[u];//因为没有进行BFS,所以计算前缀和要稍微麻烦一点,根据存贮好的每一层的节点来计算
else
sum[u]=sum[deep_num[deep[u]-][deep_num[deep[u]-].size()-]]+tot[u];
}
int query(int x,int d)
{
if (max_deep[x]<=deep[x]+d-)//如果该root没有那一层的孩子,则可以直接返回,因为肯定不需要减孩子了
return tot[x];
int val=last[x][];
int ret=tot[x];
int nd=deep[x]+d;
int L=,R=deep_num[nd].size()-,mid;
int a,b;
while (L<R)//
{ mid=(L+R)/;
//cout<<L<<" "<<R<<" "<<mid<<endl;
int nx=deep_num[nd][mid];
if (last[nx][]>=val) R=mid;
else L=mid+;
//cout<<nx<<" !!! "<<endl;
}
//cout<<"pass"<<endl;
a=deep_num[nd][L-];算出左边界,因为要算前缀和,所以L-1,这样前面的push 0在这里也起到作用了
val=last[x][];
L=,R=deep_num[nd].size()-;
while (L<R)
{
mid=R-(R-L)/;
int nx=deep_num[nd][mid];
if (last[nx][]<=val) L=mid;
else R=mid-;
// cout<<nx<<" ~~ "<<endl;
}
b=deep_num[nd][R];
//cout<<a<<" ab "<<b<<endl;
//cout<<sum[a]<<" sum "<<sum[b]<<endl;
ret-=sum[b]-sum[a]; //减去前缀和,其实还有个细节就是因为刚刚已经判断了,所以一定有孩子在这一层,所以这样减一定是合理的,不会出现没孩子也减掉的情况
return ret; }
int main()
{
int t,n,m,x,d;
scanf("%d",&t);
while (t--){
scanf("%d",&n);
init(n);
for (int i=;i<=n;i++){
int tmp;
scanf("%d",&tmp);
add(tmp,i);
}
dfs(,);
scanf("%d",&m);
while (m--){
scanf("%d%d",&x,&d);
int ans=query(x,d);
printf("%d\n",ans);
}
}
return ;
}

CSU_1414 Query On a Tree BFS序+DFS时间戳进行预处理的更多相关文章

  1. HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

    Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i].Nodes on tree i ...

  2. HDU 6191 Query on A Tree(可持久化Trie+DFS序)

    Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Othe ...

  3. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  4. S - Query on a tree HDU - 3804 线段树+dfs序

    S - Query on a tree HDU - 3804   离散化+权值线段树 题目大意:给你一棵树,让你求这棵树上询问的点到根节点直接最大小于等于val的长度. 这个题目和之前写的那个给你一棵 ...

  5. BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

    BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with ...

  6. cf276E 两棵线段树分别维护dfs序和bfs序,好题回头再做

    搞了一晚上,错了,以后回头再来看 /* 对于每次更新,先处理其儿子方向,再处理其父亲方向 处理父亲方向时无法达到根,那么直接更新 如果能达到根,那么到兄弟链中去更新,使用bfs序 最后,查询结点v的结 ...

  7. UVA10410-Tree Reconstruction(BFS序和DFS序的性质)

    Problem UVA10410-Tree Reconstruction Accept:708  Submit:4330 Time Limit: 3000 mSec Problem Descripti ...

  8. HDU5957 Query on a graph(拓扑找环,BFS序,线段树更新,分类讨论)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5957 题意:D(u,v)是节点u和节点v之间的距离,S(u,v)是一系列满足D(u,x)<=k的点 ...

  9. UVA10410 TreeReconstruction 树重建 (dfs,bfs序的一些性质,以及用栈处理递归 )

    题意,给你一颗树的bfs序和dfs序,结点编号小的优先历遍,问你可能的一种树形: 输出每个结点的子结点. 注意到以下事实: (1)dfs序中一个结点的子树结点一定是连续的. (2)bfs,dfs序中的 ...

随机推荐

  1. BInder机制总结

    BInder机制 Linux内核的基础知识 进程隔离/虚拟地址空间 操作系统当中为了保证进程间互不干扰,设计了进程隔离的技术,避免了一个进程去操作另一个进程的数据.进程隔离用到了虚拟地址空间,不同进程 ...

  2. HTTP实战

    1.建立http服务,要求: (1)提供两个基于名称的虚拟主机: www1.stuX.com,页面文件目录为/web/vhosts/www1;错误日志为/var/log/httpd/www1/erro ...

  3. POJ3295 Tautology重言式

    Tautology 思路很简单,对于p.q.r.s.t暴力枚举是0还是1,判断即可.判断时像写表达式求值那样用栈.为了方便可以从后往前,因为最后一个肯定不是运算.那几个奇奇怪怪的函数可以找规律然后转为 ...

  4. jsp采用ajax传递数组给后台controller并遍历

    ajax传递数组,期间出各种各样的问题,那叫一个头疼,网上各种查,都没有解决,最终摸索摸索加借鉴搞定,不多说,上代码 /* 复选框选定部分 */ $("#delete").clic ...

  5. 【收藏】收集的各种Python爬虫、暗网爬虫、豆瓣爬虫、抖音爬虫 Github1万+星

    收集的各种Python爬虫.暗网爬虫.豆瓣爬虫  Github 1万+星 磁力搜索网站2020/01/07更新 https://www.cnblogs.com/cilisousuo/p/1209954 ...

  6. CSU 1126 DFS前缀和

    在一棵树上找影响最小的某个点,某个点的影响是等于其他点到他的距离*其他点的权值 的和 我一开始也找不到什么好的方法,只能想到每个点暴力去判断,但是这样肯定会超时(10^5个点),又有点想用类似前缀和, ...

  7. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:测试SSH框架分层整合及验证事务是否有效

    测试框架分层的整合 HibernateTemplate 和 HibernateDaoSupport,这两个类是 Spring 为整合 Hibernate3 提供的两个工具类. HibernateTem ...

  8. 给element的confirm加自定义指令

    问题描述,因为自定义指令一般直接加在页面html标签上,但是element封装好的confirm的确认按钮没法添加自定义指令,如图: 解决办法:加个其他的隐藏标签,监听撤销事件,让其他的标签自动触发c ...

  9. C# Stream篇(七) -- NetworkStream

    NetworkStream 目录: NetworkStream的作用 简单介绍下TCP/IP 协议和相关层次 简单说明下 TCP和UDP的区别 简单介绍下套接字(Socket)的概念 简单介绍下Tcp ...

  10. 【转载】RobotFramework的Setup或Teardowm中执行多个关键字

    有时候需要在setup和teardowm中执行多个关键字 以前的做法就是重新封装一个keyword,然后调用,It’s OK 这里介绍另外一个方法,使用Run Keywords来实现 用法其实非常的简 ...