题目

其实 Kano 曾经到过由乃山,当然这名字一看山主就是 Yuno 嘛。当年 Kano 看见了由乃山,内心突然涌出了一股杜甫会当凌绝顶,一览众山小的豪气,于是毅然决定登山。

但是 Kano 总是习惯性乱丢垃圾,增重环卫工人的负担,Yuno 并不想让 Kano 登山,于是她果断在山上设置了结界……

Yuno 为了方便登山者,在山上造了 N 个营地,编号从 0 开始。当结界发动时,每当第 i(>0)号营地内有人,那么他将被传送到第 Ai(<i)号营地,如此循环,所以显然最后只会被传送到第 0 号营地。

但 Kano 并不知晓结界的情况。他登山的方法是这样的:首先分身出一个编号为 Gi 的 Kano,然后将其用投石机抛掷到营地 Di。Kano 总共做了 M 次这样的登山操作,但每次抛出去的 Kano 都被传送回了营地 0,所以 Kano 只好放弃了。

但是 Kano 在思考一个问题,到底每个营地被多少只编号不同的 Kano 经过过?

输入格式

第一行两个整数 N,M,表示山的营地数和登山次数。

接下来 N−1 行,每行一个数,第 i 行为 Ai,表示营地 i 将会传向营地 Ai。

接下来 M 行,每行两个数 Di,Gi。

输出格式

共 N 行,每行表示营地 i 有多少不同编号的 Kano 曾经通过。

样例数据

Input

5 4
0
0
1
1
4 1
3 1
2 2
4 2

Output

2
2
1
1
2

样例解释

1 号 Kano 曾被抛到 3,4 两个营地,传送轨迹分别是 3−1−0, 4−1−0

2 号 Kano 曾被抛到 2,4 两个营地,传送轨迹分别是 2−0, 4−1−0

所以 0,1,4 号营地被两只 Kano 经过过,2,3 号营地被一只 Kano 经过过。

数据规模与约定

\(5≤N≤100000,10≤M≤100000,max(Gi)≤1000000000\)

时间限制:1s

空间限制:512MB

思路

首先来想一想本题的暴力解法.

很直观的思路是对每一个营地用数组(或\(vector\)/\(set\)/\(queue\)/线段树/平衡树)维护一个集合,存放到达过该点的\(Kano\)的编号.当第\(i\)号营地里的\(Kano\)被传送到第\(A_i\)号营地时,把维护的第\(i\)号营地的集合合并到第\(A_i\)号营地的集合里.最后,每个营地的集合去重后的大小,就是曾经经过了该营地的不同编号的\(Kano\)的数量.

这样就有两个问题:一是合并的顺序;二是怎么合并两个数据结构.

第一个问题很好回答:我们可以倒序从\(n\)到\(1\)遍历序列,每次计算出该营地的答案,同时把该营地的数据合并到\(A_i\)营地.这是因为\(A_i<i\),也就是说,无论哪次合并,都是"从后面的某个营地合并到前面的某个营地".换句话说,一个营地的状态,只与它和它后面的某些营地有关.

第二个问题也很好回答,只需要按照启发式合并的思想,每次都将小的集合合并到大的集合,这样可以获得优秀的\(O(nlog_2n)\)的时间复杂度.

在代码实现中我使用了\(STL-set\),以省去去重的环节.

代码

#include<cstdio>
#include<set>
using namespace std;
int n,A[100005],m,G,D,Ans[100005],ID[100005];
set<int>x[100005];
inline void Merge(int u,int v){
if(x[ID[u]].size()<x[ID[v]].size())swap(ID[u],ID[v]);//启发式合并
for(set<int>::iterator it=x[ID[v]].begin();it!=x[ID[v]].end();it++)
x[ID[u]].insert(*it);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++){ scanf("%d",&A[i]); A[i]++; }
for(int i=1;i<=n;i++)ID[i]=i;
while(m--){ scanf("%d%d",&G,&D); x[ID[G+1]].insert(D); }
for(int i=n;i;i--){ Ans[i]=x[ID[i]].size(); if(A[i])Merge(A[i],i); }//将 i 合并到 A[i]
for(int i=1;i<=n;i++)printf("%d\n",Ans[i]);
return 0;
}

总结

如果把题给的条件看成\(<i,A_i>\)的有向边,那么可以建出一个\(DAG\)图,而上面提到的倒序从\(n\)到\(1\)就是该图的一个拓扑序,因此我们可以倒着合并.

爬山 启发式合并 / STL的更多相关文章

  1. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

    [NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...

  2. 【BZOJ1483】【HNOI2009】梦幻布丁(启发式合并,平衡树)

    [BZOJ1483][HNOI2009]梦幻布丁 题面 题目描述 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1 ...

  3. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  4. 【BZOJ3123】森林(主席树,启发式合并)

    题意:一个带点权的森林,要求维护以下操作: 1.询问路径上的点权K大值 2.两点之间连边 n,m<=80000 思路:如果树的结构不发生变化只需要维护DFS序 现在因为树的结构发生变化,要将两棵 ...

  5. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

  6. 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并

    启发式合并而已啦,, 调试时发现的错误点:insert后没有splay,把要拆开的树的点插入另一个树时没有把ch[2]和fa设为null,找第k大时没有先减k,,, 都是常犯的错误,比赛时再这么粗心就 ...

  7. 51nod 1515 明辨是非 并查集 + set + 启发式合并

    给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等:否则输出NO,并忽略此次操作. 当p为0时,如果第x变量和第y个变量可以不相等,则输 ...

  8. [BZOJ 1483][HNOI 2009]梦幻补丁(有序表启发式合并)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1483 分析: 先将不同的颜色的出现位置从小到大用几条链表串起来,然后统计一下答案 对于 ...

  9. 【BZOJ-2809】dispatching派遣 Splay + 启发式合并

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2334  Solved: 1192[Submi ...

随机推荐

  1. xadmin使用

    xadmin使用 官方 使用参考

  2. 一道有趣的for循环题

    一道有趣的for循环题 今天在复习js基础知识时发现了一个for循环的题,第一眼看到直接懵逼了,没想到for循环竟然还可以这样玩?涨姿势了. 题目是这样的 for(i=0, j=0; i<10, ...

  3. Java基于SSM在线学习系统设计与实现

                 Spring+SpringMVC+MyBatis+Bootstrap+Vue开发在线学习系统 本课题的主要内容是开发基于Java EE的在线学习平台,使用MVC经典开发模式. ...

  4. 305. 岛屿数量 II

    题目: 假设你设计一个游戏,用一个 m 行 n 列的 2D 网格来存储你的游戏地图. 起始的时候,每个格子的地形都被默认标记为「水」.我们可以通过使用 addLand 进行操作,将位置 (row, c ...

  5. mysql 连接权限

    命令解释: . 第一个表示库,第二个表示表; .对全部数据库的全部表授权,so.ok 表示只对so这个库中的ok表授权 root 表示要给哪个用户授权,这个用户可以是存在的用户,也可以是不存在的 '% ...

  6. UI自动化测试的Page Object模式

    在UI级的自动化测试框架中,当页面样式改变或者页面元素属性改变,那么代码也要随之进行修改,如何做到高效快速的修改代码来适应这些改变呢,这个时候可以引入Page Object模式,也是页面对象设计模式. ...

  7. vue.js中使用离线检测

    Html5在window.navigator对象上添加了一个属性onLine 返回布尔值 true表示在线.同时新增了两个事件: window.addEventListener('online', f ...

  8. [Code+#4] 最短路 - 建图优化,最短路

    最短路问题,然而对于任意\(i,j\),从\(i\)到\(j\)可以只花费\((i xor j) \cdot C\) 对每个点\(i\),只考虑到\(j\)满足\(j=i xor 2^k, j \le ...

  9. vue 项目初始化

    初始化 vue init webpack-simple myproject 安裝 npm install 运行 npm run dev 访问地址 http://localhost:8080/ 安装we ...

  10. 动图演示23个鲜为人知的VSCode快捷键

    动图演示23个鲜为人知的VSCode快捷键 原文地址:dev.to/devmount/23… 代码同步浏览器 安装vccode 安装live server插件 尽管我在VS Code中经常使用许多快捷 ...