You are given a tree that represents a hierarchy in a company, where the parent of node u is their direct manager.

Each employee is assigned a project, and multiple employees can be assigned to the same project. When it is time for the presentation of the ith project, all employees u that are assigned that project and their direct and indirect managers must attend the presentation (u and their manager and their manager's manager and so on until the CEO).

Find for each project the number of people attending its presentation.

Input

The first line of input is n and m (1 ≤ m ≤ n ≤ 106), the number of employees and the number of projects, respectively.

The second line of input contains n integers ai (1 ≤ ai ≤ m), where ai is the project assigned to the ith employee. It is guaranteed that each project has at least one employee assigned to it.

The third line of input contains n integers pi (0 ≤ pi ≤ n), where pi is the direct manager of the ith employee. If pi = 0, then the ith
employee is the CEO and does not have a manager. It is guaranteed that
there is only one CEO, and this CEO is a direct or indirect manager of
all other employees.

Output

Output m integers, where the ith integer is the number of people attending the presentation of the ith project.

Example

Input
6 4
1 2 4 3 2 4
0 1 1 3 3 2
Output
1 4 3 4 
题解:首先根据题意建树,每个节点有对应的任务(1~m),如果一个人处理i任务,那么他所有的祖先都得参与到当中,对于每一个任务,求参与到其中的人的数量。
首先DFS序跑图,得到每个节点的入时间序,时间序对应的原节点,深度,走2^0步得到的节点。
然后对于每一个任务:假设其中有x个人执行这个任务,我们首先将其按DFS序从小到大排序,然后有对应公式:sum+=dep[i]-dep[LCA(i-1,i)]。
那么就该想如何实现这个过程了,下面是用的vector存储:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
int w[maxn],x,root,cnt;
int Start[maxn],End[maxn],dep[maxn],par[][maxn],Rev[maxn];
vector<int>G[maxn],vv[maxn],ans;
void DFS(int u,int pre,int d)
{
par[][u]=pre;//u向上走2^0走到pre节点
dep[u]=d;//u的深度
Start[u]=++cnt;//DFS序对应值
Rev[cnt]=u;//将其反过来转换为原来的节点
for(int i=;i<G[u].size();i++){
DFS(G[u][i],u,d+);
}
End[u]=cnt;
}
int LCA(int u,int v)
{
if(dep[u]>dep[v])swap(u,v);
for(int k=;k<;k++){//让u和v走到同一深度
if((dep[v]-dep[u])>>k&){//这里简单理解下就是将u和v的距离用二进制表示,每一位1将其变为0
v=par[k][v];
}
}
if(u==v)return u;
for(int k=;k>=;k--){
if(par[k][u]!=par[k][v]){
u=par[k][u];
v=par[k][v];
}
}
return par[][u];
}
int main()
{
ios::sync_with_stdio();
int n,m;
cin>>n>>m;
for(int i=;i<=n;i++)cin>>w[i];
for(int i=;i<=n;i++){
cin>>x;
if(x!=){
G[x].push_back(i);
}
else
root=i;
}
DFS(root,-,);
for(int k=;k<;k++){//预处理par数组
for(int v=;v<=n;v++){
if(par[k][v]==-)par[k+][v]=-;
else par[k+][v]=par[k][par[k][v]];
}
}
for(int i=;i<=n;i++){
vv[w[i]].push_back(Start[i]);
}
for(int i=;i<=m;i++){
sort(vv[i].begin(),vv[i].end());//按照DFS序递增排序,是为了不重复答案
int sum=;
for(int j=;j<vv[i].size();j++){
if(j==)sum+=dep[Rev[vv[i][j]]];
else sum+=dep[Rev[vv[i][j]]]-dep[LCA(Rev[vv[i][j-]],Rev[vv[i][j]])];
}
ans.push_back(sum);
}
for(int i=;i<ans.size();i++)cout<<ans[i]<<" ";
cout<<endl;
return ;
}

D - Project Presentation(DFS序+倍增LCA)的更多相关文章

  1. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  2. luogu3320 寻宝游戏 (dfs序+倍增lca+set)

    一定是从随便某个点开始,然后按着dfs序的顺序跑一圈是最好的 所以说,新加一个点x,就减少了dis(pre,next),增加了dis(pre,x),dis(x,nxt) 删掉一个点同理 这个可以用se ...

  3. 洛谷P3379 【模板】最近公共祖先(LCA)(dfs序+倍增)

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...

  4. dfs序 + RMQ = LCA

    dfs序是指你用dfs遍历一棵树时,每个节点会按照遍历到的先后顺序得到一个序号.然后你用这些序号,可以把整个遍历过程表示出来. 如上图所示,则整个遍历过程为1 2 3 2 4 5 4 6 4 2 1 ...

  5. bzoj 2819 Nim(BIT,dfs序,LCA)

    2819: Nim Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1596  Solved: 597[Submit][Status][Discuss] ...

  6. bzoj3306: 树(dfs序+倍增+线段树)

    比较傻逼的一道题... 显然求子树最小值就是求出dfs序用线段树维护嘛 换根的时候树的形态不会改变,所以我们可以根据相对于根的位置分类讨论. 如果询问的x是根就直接输出整棵树的最小值. 如果询问的x是 ...

  7. CF 208E - Blood Cousins dfs序+倍增

    208E - Blood Cousins 题目:给出一棵树,问与节点v的第k个祖先相同的节点数有多少个. 分析: 寻找节点v的第k个祖先,这不就是qtree2简化版吗,但是怎么统计该祖先拥有多少个深度 ...

  8. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  9. 蓝皮书:异象石 【dfs序+lca】

    题目详见蓝皮书[算法竞赛:进阶指南]. 题目大意: 就是给你一颗树,然后我们要在上面进行三种操作:  1.标记某个点  或者  2.撤销某个点的标记  以及   3.询问标记点在树上连通所需的最短总边 ...

随机推荐

  1. GTK入门

    环境准备 官网下载 GTK 源码包,因为本机 GLib 版本不够,下载一个非最新版的 GTK3.8.0 先学习用 直接阅读 "/gtk+-3.8.0/docs/reference/gtk/h ...

  2. 洛谷 AT2827 LIS

    题目传送门 解题思路: 用f[i]表示长度为i的最长上升子序列的最小的末尾. AC代码: #include<iostream> #include<cstdio> #includ ...

  3. java多线程之volatile关键字

    public class ThreadVolatile extends Thread { public boolean flag=true; @Override public void run() { ...

  4. C/C++源程序到可执行程序的过程

    源程序.cpp  预处理得到 预处理文件.i   编译得到 汇编文件.S    汇编得到 目标文件.o     链接得到 可执行文件 例子:main.cpp  fun.cpp fun.h #inclu ...

  5. Unix网络编程学习 < 一 >

    #include "unp.h" int main(int argc , char**argv) { int sockfd , n; //sockfd套接字描述符 ]; struc ...

  6. Odd sum (对本菜鸡来说是个极坑题)

    https://codeforces.com/problemset/problem/797/B time limit per test 1 second memory limit per test 2 ...

  7. Codeforces 1295B - Infinite Prefixes

    题目大意: 给定一个长度为n的字符串s,由字符0和1组成 你可以让这个字符串s无限延长 就令字符串t=sssssss...... 求字符串t有多少个前缀字符串中,0的个数减去1的个数等于x 解题思路: ...

  8. 计蒜客 密码锁(BFS)

    https://www.jisuanke.com/course/1797/121114 Description 现在一个紧急的任务是打开一个密码锁.密码由四位数字组成,每个数字从 1 到 9 进行编号 ...

  9. 浅谈对RabbitMQ的认识

    一.什么是消息队列?什么时候使用它? 在传统的web架构中(此处特指Java SSM架构),用户在web中进行了某项需要和后台产生交互的操作后,一般都要开启一个session,从view层开始,由co ...

  10. PAT Advanced 1127 ZigZagging on a Tree (30) [中序后序建树,层序遍历]

    题目 Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree c ...