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. nginx常用内置变量

    $args #请求中的参数值 $query_string #同 $args $arg_NAME #GET请求中NAME的值 $is_args #如果请求中有参数,值为"?",否则为 ...

  2. 11. react 基础 使用charles 模拟接口数据

    charles参考文档 charles官网 模拟数据 模拟 axios 请求的数据 eg: 1. 编写 axios 请求 axios.get('/api/xxx') .then(()=>{ale ...

  3. Map的6种遍历方法

    声明:迁移自本人CSDN博客https://blog.csdn.net/u013365635 探讨有几种遍历Map的方法其实意义并不大,网上的文章一般讲4种或5种的居多,重要的是知道遍历的内涵,从遍历 ...

  4. 201612-2 工资计算 Java

    思路: 税+税后所得A=税前工资S. 因为工资是整百的数,每次减100来判断.好理解但是超时. import java.util.Scanner; //只有90分,超时了 public class M ...

  5. windows下关闭自动更新方法

    第一种方法: 1.windows+R键打开运行窗口,输入services.msc 2.找到windows update服务右键属性 第二种方法 Win键+R键在弹出的运行对话框中输入gpedit.ms ...

  6. Mybatis之一级缓存(七)

    1. 介绍 Mybatis缓存分为一级缓存和二级缓存,在本节中我们介绍下一级缓存的使用及其特性 MyBatis的一级缓存是在一个Session域内有效的,当Session关闭后,缓存内容也随之销毁.缓 ...

  7. POJ 1850:Code 组合数学

    Code Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 8710   Accepted: 4141 Description ...

  8. Storm 重启排查

    Storm实战常见问题及解决方案 https://www.cnblogs.com/catkins/p/5302634.html Storm 重启排查(续) https://www.iteye.com/ ...

  9. 实体机安装Ubuntu系统

    今天windows突然蓝屏了,索性安装个 Ubuntu 吧,这次就总结一下实体机安装 Ubuntu 的具体步骤 note: 本人实体机为笔记本 型号为:小米pro U盘为金士顿:8G 安装系统:Ubu ...

  10. DB---WAL技术

    摘要:这个WAL技术也需要加以整理,即 write-ahead logging (预写式日志),待整理...