Codeforces 208E. Blood Cousins
题目大意:
小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=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e6+;
int fir[N],from[N<<],to[N<<],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int f[N][],dep[N],son[N],sz[N];//f是倍增数组,dep是节点深度,son是重儿子,sz是子树大小
void dfs1(int x)//预处理上面四个数组
{
dep[x]=dep[f[x][]]+; sz[x]=; int mx=;
for(int i=;i<=;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=fir[x];i;i=from[i])
{
int &v=to[i]; if(v==f[x][]) continue;
f[v][]=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][]||v==son[x]) continue;
dfs2(v,);//走轻儿子
}
int R=dfs_clock,t=lower_bound(d+,d+Q+,(dat){x,,})-d;//R是轻儿子子树右区间,t是第一个u为x的询问的位置
dfs2(son[x],);//最后走重儿子并保留cnt
for(int i=L;i<=R;i++) cnt[ dep[id[i]] ] ++;//枚举轻儿子子树,更新cnt
for(int i=t;d[i].x==x;i++) { ans[d[i].id]=cnt[dep[d[i].y]]-; }//更新ans
if(!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=;i<=n;i++)
{
a=read();
add(a,i);
if(!a) rt[++tot]=i;
}
for(int i=;i<=tot;i++) dfs1(rt[i]);
Q=read();
for(int i=;i<=Q;i++)
{
a=read(),b=read(); int t=a;
for(int j=;j>=;j--) if(b&(<<j)) t=f[t][j];
d[i].x=t,d[i].y=a,d[i].id=i;
}
sort(d+,d+Q+);
for(int i=;i<=tot;i++) dfs2(rt[i],);
for(int i=;i<=Q;i++) printf("%d ",ans[i]);
return ;
}
Codeforces 208E. Blood Cousins的更多相关文章
- Codeforces 208E - Blood Cousins(树上启发式合并)
208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...
- CF 208E - Blood Cousins dfs序+倍增
208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...
- Codeforces 246E - Blood Cousins Return (树上启发式合并)
246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...
- Codeforces 246E Blood Cousins Return(树上启发式合并)
题目链接 Blood Cousins Return #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) f ...
- CF 208E. Blood Cousins [dsu on tree 倍增]
题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...
- [cf contest246] E - Blood Cousins Return
[cf contest246] E - Blood Cousins Return time limit per test 3 seconds memory limit per test 256 meg ...
- CF208E Blood Cousins
Blood Cousins 题目描述 小C喜欢研究族谱,这一天小C拿到了一整张族谱. 小C先要定义一下k-祖先. x的1-祖先指的是x的父亲 x的k-祖先指的是x的(k-1)-祖先的父亲 小C接下来要 ...
- CF 246E. Blood Cousins Return [dsu on tree STL]
题意: 一个森林,求k级后代中多少种不同的权值 用set维护每个深度出现的权值 一开始一直在想删除怎么办,后来发现因为当前全局维护的东西里都是当前子树里的,如果要删除那么当前一定是轻儿子,直接清空se ...
- codeforces246E Blood Cousins Return
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- linux tcp/ip 调优
sysctl 变量修改方法:sysctl –a 使用 sysctl 命令修改系统变量,和通过编辑 sysctl.conf 文件来修改系统变量两种.但并不是所有的 变量都可以在这个模式下设定. 注:sy ...
- springboot+UEditor图片上传
springboot+UEDitor百度编辑器整合图片上记录于此 1.下载ueditor插件包,解压到static/ueditor目录下 2.在你所需实现编辑器的页面引用三个JS文件 1) uedi ...
- [web 安全] xxe
一.探测漏洞 1.是否支持实体解析. 2.是否支持外部实体解析. 2.1 直接读取本地文件: 2.2 远程文件: 3.不回显错误,则用 blind xxe.(先获取本地数据,然后带着本地数据去访问恶意 ...
- 前端小姐姐学PHP之(一)
作为一个前端不懂后台那是不对的,嘻嘻,来走一波... 一.安装 **我这里用的是phpStudy和phpStrom** 1.安装phpStudy 链接:https://pan.baidu.com/s/ ...
- Ubuntu Server下MySql数据库备份脚本代码
明: 我这里要把MySql数据库存放目录/var/lib/mysql下面的pw85数据库备份到/home/mysql_data里面,并且保存为mysqldata_bak_2012_04_11.tar. ...
- export default{} 和 new Vue()都是什么意思
在生成.导出.导入.使用 Vue 组件的时候,有些新手就会常常被位于不同文件的 new Vue() 和 export default{} 搞得晕头转向.它们含义到底是什么,又有什么异同呢? 首先,Vu ...
- Python---基础---list(列表)
2019-05-20 一. # append() 向列表末尾追加新元素 返回值Nonelist1 = [1,2,3,4,5]print(id(list1))list1.append(6)prin ...
- hdu 5963:朋友
刚看到这题时感觉是树上博弈,然后我开始用一维的数据找规律.发现在一维的树上,如果把各边的值合在一起当成一个二进制数,那么,ans只与奇偶性有关,于是,我提出了一个比较大胆的假设:若连接在root上的所 ...
- matplotlib.pyplot 包
import matplotlib.pyplot as plt 图片的打开和保存: from PIL import Image img=Image.open('....') img.save('... ...
- 如何从word中复制内容到网站后台编辑器中
word图片转存,是指UEditor为了解决用户从word中复制了一篇图文混排的文章粘贴到编辑器之后,word文章中的图片数据无法显示在编辑器中,也无法提交到服务器上的问题而开发的一个操作简便的图片转 ...