传送门

题目大意:

小C喜欢研究族谱,这一天小C拿到了一整张族谱。

小C先要定义一下k-祖先。

  • x的1-祖先指的是x的父亲
  • x的k-祖先指的是x的(k-1)-祖先的父亲

小C接下来要定义k-兄弟

  • x的k-兄弟指的是与x的k-祖先相同的人
  • 如果不存在k-祖先那么x没有k-兄弟

小C想问问你,x到底有多少k-兄弟?小C打算问Q次这样的问题。

数据范围:

$n<=10^5,Q<=10^5$

$dsu\ on\ tree$ 基础题,当然也有显然的在线做法

对于每个询问 $(x,k)$,不妨转换为 $(u,v)$ ,表示求 $u$ 的子树中,与 $v$ 深度相同的节点数

考虑怎么离线搞,直接 $dsu\ on\ tree$ 维护一个统计各个深度节点数的数组 $cnt$ 即可

每次 $dfs$ 时最后 $dfs$ 重儿子,从而保留重儿子的 $cnt$ ,这样与每个节点 $u$ 有关的询问只要暴力枚举轻儿子子树即可

复杂度就是启发式合并的 $nlog_n$

具体看代码,注意数据是森林

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }return x*f;
}
const int N=2e6+7;
int fir[N],from[N<<1],to[N<<1],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int f[N][21],dep[N],son[N],sz[N];//f是倍增数组,dep是节点深度,son是重儿子,sz是子树大小
void dfs1(int x)//预处理上面四个数组
{dep[x]=dep[f[x][0]]+1; sz[x]=1; int mx=0;for(int i=1;i<=20;i++) f[x][i]=f[f[x][i-1]][i-1];for(int i=fir[x];i;i=from[i]){int &v=to[i]; if(v==f[x][0]) continue;f[v][0]=x; dfs1(v);if(sz[v]>sz[son[x]]) son[x]=v;sz[x]+=sz[v];}
}
struct dat{int x,y,id;inline bool operator < (const dat &tmp) const {return x<tmp.x;}
}d[N];//存询问
int n,Q;
int cnt[N],ans[N],id[N],dfs_clock;//id是dfs序为i的节点编号
void dfs2(int x,bool flag)//flag判断是否保留cnt
{id[++dfs_clock]=x; int L=dfs_clock;//轻儿子子树dfs序的左区间if(!son[x]) { if(flag) cnt[dep[x]]++; return; }for(int i=fir[x];i;i=from[i]){int &v=to[i]; if(v==f[x][0]||v==son[x]) continue;dfs2(v,0);//走轻儿子
    }int R=dfs_clock,t=lower_bound(d+1,d+Q+1,(dat){x,0,0})-d;//R是轻儿子子树右区间,t是第一个u为x的询问的位置dfs2(son[x],1);//最后走重儿子并保留cntfor(int i=L;i<=R;i++) cnt[ dep[id[i]] ] ++;//枚举轻儿子子树,更新cntfor(int i=t;d[i].x==x;i++) { ans[d[i].id]=cnt[dep[d[i].y]]-1; }//更新ansif(!flag) for(int i=L;i<=dfs_clock;i++) cnt[ dep[id[i]] ]--;//清空cnt
}
int rt[N],tot;//注意是森林,要存每个数的根
int main()
{n=read(); int a,b;for(int i=1;i<=n;i++){a=read();add(a,i);if(!a) rt[++tot]=i;}for(int i=1;i<=tot;i++) dfs1(rt[i]);Q=read();for(int i=1;i<=Q;i++){a=read(),b=read(); int t=a;for(int j=20;j>=0;j--) if(b&(1<<j)) t=f[t][j];d[i].x=t,d[i].y=a,d[i].id=i;}sort(d+1,d+Q+1);for(int i=1;i<=tot;i++) dfs2(rt[i],0);for(int i=1;i<=Q;i++) printf("%d ",ans[i]);return 0;
}

转载于:https://www.cnblogs.com/LLTYYC/p/10946141.html

Codeforces 208E. Blood Cousins相关推荐

  1. CodeForces - 208E Blood Cousins(树上倍增+二分/树上启发式合并)

    题目链接:点击查看 题目大意:给出n棵树,再给出m个询问,每次询问给出两个整数u和k,先假设u在k层之上的祖先是p,问与u在同一层深度,并且公共祖先都是p的节点有多少个 题目分析:因为先要求出u在第k ...

  2. CodeForces - 246E Blood Cousins Return(树上启发式合并)

    题目链接:点击查看 题目大意:给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u 和 k,问以 u 为根节点的子树下 ...

  3. CF 208E Blood Cousins (dus on tree)

    题目链接:https://codeforces.com/contest/208/problem/E 题意:n个节点,组成森林.m个询问,一个询问由(v,p)组成,问v的p-cousin有多少,v的p- ...

  4. cf246E. Blood Cousins Return

    cf246E. Blood Cousins Return 题意: 给你一个森林,每个点都有自己的种类,问以v为根节点的子树中,与v距离为k的节点有多少种 题解: 和cf208E. Blood Cous ...

  5. cf208E. Blood Cousins

    cf208E. Blood Cousins 题意: 给你一个森林,m次询问,每次询问(v,p),问v的p-cousin有多少?p-cousin指的是与v在同一层且他们到lca的距离都是p 题解: 对于 ...

  6. Blood Cousins (dsu on tree + 求第k级祖先)

    题目链接: Blood Cousins 大致题意 给出一片森林, 询问对于给定的点而言, 其k级祖先中有多少个点的深度和当前节点相同. 解题思路 dsu on tree 对于每个询问x, k而言, 我 ...

  7. CF 246E. Blood Cousins Return [dsu on tree STL]

    题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...

  8. 【Codeforces #130 Div2】Solutions

    [208A  Dubstep] http://codeforces.ru/problemset/problem/208/A 题目大意:一个句子被添加了若干"WUB",问原句. 将W ...

  9. dsu on tree 题集 + ac代码

    文章目录 **入门讲解** **[600E - Lomsat gelral](https://codeforces.ml/problemset/problem/600/E)** **[树上数颜色](h ...

  10. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

最新文章

  1. android支付宝调用
  2. 化解谷歌AI霸权的另一种思路?开发平台的生态围剿
  3. Subversion存储库中“分支”,“标记”和“主干”的含义是什么?
  4. Java-protected的使用范围
  5. java——File类常用方法
  6. std::make_any
  7. Java的组合排列问题
  8. ASP.NET Core 开源项目 nopCommerce,一款沉淀13年的电商开源佳作!
  9. Java笔记-使用System.gc()进行内存回收
  10. 零信任技术进阶篇(关键技术及挑战、BeyondCorp安全模型)
  11. 雷电模拟器多开cpu优化_哪个电脑手游模拟器好用 安卓手游模拟器测试对比排行榜...
  12. Web入门之VScode连接数据库sql server(超详细)
  13. T60 Fan Error 解决办法.转自ZOL产品论坛-作者zxymb
  14. 手机整人脚本html,教大家用vbs代码制作恶搞整人
  15. QC1.0、QC2.0、QC3.0、QC4.0协议介绍
  16. Java实现百度贴吧自动签到器
  17. [COGS755]山海经
  18. 程序员转行都去干嘛了?产品经理很正常,这位卖烧饼的也太强了
  19. eclipse命令大全
  20. 需求工程方法及技术汇总

热门文章

  1. springmvc源码-参数解析
  2. Set集合之HashSet添加的数据是如何保证不重复的
  3. Hadoop系列教程:服务器基础环境
  4. 网络规划---网络计划图的时间参数计算
  5. Tomcat历史版本下载
  6. Jupyter Notebook 作图显示中文
  7. 验证码计时 -- UIButton setTitle 闪烁问题解决方案
  8. Hibernate 的HQL和sql有什么区别
  9. 如何为SUSE配置IP地址,网关和DNS
  10. 类别的作用?继承和类别在实现中有何区别