题面

一棵以

1

1

1 为根的

N

N

N 个节点的有根树,

Q

Q

Q 次询问,每次问一个点

u

u

u 的

k

k

k 级兄弟有多少个(第

k

k

k 代祖先的第

k

k

k 代孩子),如果没有则输出 0

N

,

Q

1

0

6

N,Q\leq 10^6

N,Q≤106 。

题解

像这种一个 log 可过的题目就是拿来 O(n) 做的

狗狗有言:挺板的长链剖分。

我们用离线+长链剖分来解决第

k

k

k 代孩子的问题,每个链顶存一个数组,表示每一代孩子的个数,把轻儿子的链合并。这个是长链剖分的常有操作,总共复杂度

O

(

n

)

O(n)

O(n) 。

如何

O

(

1

)

O(1)

O(1) 找

k

k

k 级祖先,这个很简单,不必用倍增。只需要把询问挂到树上,然后

d

f

s

\rm dfs

dfs 临时用一个数组栈存祖先就行了。

CODE

唉,又水了一篇

全程不用 vector ,常数极小

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define eps (1e-4)
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) putchar('0');
else if(x < 0) putchar('-'),putpos(-x);
else putpos(x);
}
const int MOD = 1000000007;
int n,m,s,o,k;
int hd[MAXN],v[MAXN],nx[MAXN],cnt;
void ins(int x,int y) {
v[++ cnt] = y; nx[cnt] = hd[x];
hd[x] = cnt; return ;
}
int d[MAXN],le[MAXN],son[MAXN]; int hd2[MAXN],nx2[MAXN];
int U[MAXN],kk[MAXN],fa[MAXN],as[MAXN];
int st[MAXN],tp;
int ar[MAXN<<1],he[MAXN],CN;
void dfs0(int x,int ff) {
d[x] = d[ff] + 1;
st[++ tp] = x;
for(int i = hd2[x];i;i = nx2[i]) {
if(kk[i] >= d[x]) fa[i] = 0;
else fa[i] = st[tp-kk[i]];
}
hd2[x] = 0;
for(int i = hd[x];i;i = nx[i]) {
dfs0(v[i],x);
le[x] = max(le[x],le[v[i]] + 1);
if(le[v[i]] >= le[son[x]]) son[x] = v[i];
}
tp --;
return ;
}
void dfs(int x,int ff) {
he[x] = ++ CN;
ar[he[x]] ++;
if(son[x]) dfs(son[x],x);
for(int i = hd[x];i;i = nx[i]) {
if(v[i] != son[x]) {
dfs(v[i],x);
for(int j = 0;j <= le[v[i]];j ++) {
ar[he[x]+j+1] += ar[he[v[i]]+j];
}
}
}
for(int i = hd2[x];i;i = nx2[i]) {
int le = d[U[i]] - d[x];
as[i] = ar[he[x]+le] - 1;
}
return ;
}
int main() {
n = read();m = read();
for(int i = 2;i <= n;i ++) {
s = read();o = i;
ins(s,o);
}
for(int i = 1;i <= m;i ++) {
U[i] = s = read();kk[i] = read();
nx2[i] = hd2[s]; hd2[s] = i;
}
dfs0(1,0);
for(int i = 1;i <= m;i ++) {
if(!fa[i]) continue;
nx2[i] = hd2[fa[i]]; hd2[fa[i]] = i;
}
dfs(1,0);
for(int i = 1;i <= m;i ++) {
putnum(as[i]);
if(i < m) putchar(' ');
}ENDL;
return 0;
}

最新文章

  1. nginx中相关配置
  2. 【转】工控老鬼】西门子S7200入门&amp;精通【1】S7200硬件大全
  3. silverlight中 Storyboard(动画)的使用,实现球的上下循环移动,左右移动,及旋转功能
  4. day4之函数
  5. 浅谈java性能分析
  6. MySQL Innodb的两种表空间方式
  7. 秀尔算法:破解RSA加密的“不灭神话”
  8. BZOJ 1266 上学路线route(最小割)
  9. RubyGems使用
  10. Linux下卸载ORACLE的多种方法(转)
  11. 菜鸟认识揭开DLL木马
  12. android动画介绍之 自己定义Animation动画实现qq抖一抖效果
  13. Windows环境下安装Oracle数据库
  14. 雷林鹏分享:jQuery EasyUI 数据网格 - 自定义分页
  15. 大数据:Parquet文件存储格式
  16. 前端框架VUE----补充
  17. Java学习--基本数据类型的定义和运算2
  18. CentOS6.8 yum 安装 mysql5.7.12 完美步骤
  19. Android SurfaceView播放视频时横竖屏的调整
  20. 20165218 2017-2018-1《Java程序设计》第二周学习总结

热门文章

  1. 快速 IO
  2. .NET 处理[未能为 SSLTLS 安全通道建立信任关系]问题
  3. C#中的String Interpolation
  4. flink-执行模式
  5. 【python基础】第07回 运算符和流程控制 2
  6. 数据库 OLAP、OLTP是什么?相同和不同?适用场景
  7. labview从入门到出家4--用事件结构实现运算功能
  8. 如何用天气预警API接口进行快速开发
  9. Wpf 多指应用开发解析
  10. 【New】Code Insertion