\(\mathcal{Description}\)

  \(n\) 个点,第 \(i\) 个点能走向第 \(d_i\) 个点,但从一个点出发至多走 \(k\) 步。对于每个点,求有多少点能够走到它。

  \(n\le5\times10^5\)。

\(\mathcal{Solution}\)

  显然这些点构成一片内向基环树森林。考虑每个点的贡献,若其向上走 \(k\) 步仍不能到环上,那一定只在树内对一条链贡献,树上差分一下。否则,该点会向到根的每个点贡献,并向环上一段连续的点贡献,后者维护一个数列差分亦可统计,就切掉啦。

  复杂度 \(\mathcal O(n)\)。

\(\mathcal{Code}\)

#include <cstdio>
#include <vector>
#include <algorithm> inline int rint () {
int x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x;
} inline void wint ( const int x ) {
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
} const int MAXN = 5e5;
int n, K, d[MAXN + 5], ans[MAXN + 5], stk[MAXN + 5], top, ccnt;
bool vis[MAXN + 5], oncir[MAXN + 5], inq[MAXN + 5];
int dep[MAXN + 5], fa[MAXN + 5], dir[MAXN + 5], tag[MAXN + 5], add[MAXN * 2 + 5];
std::vector<int> cir[MAXN + 5], adj[MAXN + 5]; inline void findCir ( const int u ) {
if ( vis[u] ) return ;
vis[u] = true, stk[++ top] = u, inq[u] = true;
if ( inq[d[u]] ) {
int v; ++ ccnt;
do {
oncir[v = stk[top --]] = true;
cir[ccnt].push_back ( v );
} while ( v ^ d[u] );
std::reverse ( cir[ccnt].begin (), cir[ccnt].end () );
}
findCir ( d[u] ), inq[u] = false;
} inline void solveTree ( const int u, int p, const int rtid, const int L ) {
++ tag[u];
if ( dep[u] <= K ) {
int tar = K - dep[u] + 1;
if ( tar >= L ) tar = L - 1;
++ add[rtid + 1], -- add[rtid + 1 + tar];
} else {
-- tag[fa[p]], p = dir[p];
}
for ( int i = 0, v; i ^ adj[u].size (); ++ i ) {
if ( !oncir[v = adj[u][i]] ) {
dep[dir[u] = v] = dep[u] + 1, fa[v] = u;
solveTree ( v, p, rtid, L );
}
}
} inline int calc ( const int u ) {
int ret = tag[u];
for ( int i = 0, v; i ^ adj[u].size (); ++ i ) {
if ( !oncir[v = adj[u][i]] ) {
ret += calc ( v );
}
}
return ans[u] += ret, ret;
} inline void solveCir ( std::vector<int>& cir ) {
int L = cir.size ();
for ( int i = 0; i <= L << 1; ++ i ) add[i] = 0;
for ( int i = 0, u; i < L; ++ i ) {
dep[u = cir[i]] = 1;
solveTree ( u, u, i, L ), calc ( u );
}
for ( int i = 1; i < L * 2; ++ i ) add[i] += add[i - 1];
for ( int i = 0; i < L; ++ i ) ans[cir[i]] += add[i] + add[i + L];
} int main () {
freopen ( "travel.in", "r", stdin );
freopen ( "travel.out", "w", stdout );
n = rint (), K = rint ();
for ( int i = 1; i <= n; ++ i ) adj[d[i] = rint ()].push_back ( i );
for ( int i = 1; i <= n; ++ i ) top = 0, findCir ( i );
for ( int i = 1; i <= ccnt; ++ i ) solveCir ( cir[i] );
for ( int i = 1; i <= n; ++ i ) wint ( ans[i] ), putchar ( '\n' );
return 0;
}

\(\mathcal{Details}\)

  考场上想得久了点 qwq……最神奇的是兔子爆排一般是因为标算写假而测试代码是对的。(

Solution -「LOCAL」人口迁徙的更多相关文章

  1. Solution -「LOCAL」二进制的世界

    \(\mathcal{Description}\)   OurOJ.   给定序列 \(\{a_n\}\) 和一个二元运算 \(\operatorname{op}\in\{\operatorname{ ...

  2. Solution -「LOCAL」大括号树

    \(\mathcal{Description}\)   OurTeam & OurOJ.   给定一棵 \(n\) 个顶点的树,每个顶点标有字符 ( 或 ).将从 \(u\) 到 \(v\) ...

  3. Solution -「LOCAL」过河

    \(\mathcal{Description}\)   一段坐标轴 \([0,L]\),从 \(0\) 出发,每次可以 \(+a\) 或 \(-b\),但不能越出 \([0,L]\).求可达的整点数. ...

  4. Solution -「LOCAL」Drainage System

    \(\mathcal{Description}\)   合并果子,初始果子的权值在 \(1\sim n\) 之间,权值为 \(i\) 的有 \(a_i\) 个.每次可以挑 \(x\in[L,R]\) ...

  5. Solution -「LOCAL」Burning Flowers

      灼之花好评,条条生日快乐(假装现在 8.15)! \(\mathcal{Description}\)   给定一棵以 \(1\) 为根的树,第 \(i\) 个结点有颜色 \(c_i\) 和光亮值 ...

  6. Solution -「LOCAL」画画图

    \(\mathcal{Description}\)   OurTeam.   给定一棵 \(n\) 个点的树形随机的带边权树,求所有含奇数条边的路径中位数之和.树形生成方式为随机取不连通两点连边直到全 ...

  7. Solution -「LOCAL」ZB 平衡树

    \(\mathcal{Description}\)   OurOJ.   维护一列二元组 \((a,b)\),给定初始 \(n\) 个元素,接下来 \(m\) 次操作: 在某个位置插入一个二元组: 翻 ...

  8. Solution -「LOCAL」舟游

    \(\mathcal{Description}\)   \(n\) 中卡牌,每种三张.对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) ...

  9. Solution -「LOCAL」充电

    \(\mathcal{Description}\)   给定 \(n,m,p\),求序列 \(\{a_n\}\) 的数量,满足 \((\forall i\in[1,n])(a_i\in[1,m])\l ...

随机推荐

  1. spring cloud 与spring boot的版本对应总结

    1.前言 一开始不理解为什么使用 spring boot 高版本  ,却没有对应的spring cloud版本 ,还以为最高版本的 spring cloud 会向上兼容  . 这个坑 ,没有人告诉我, ...

  2. iView 用renderContent自定义树组件

    iview的树组件在有默认选中状态的时候默认选中状态的样式改变有bug,默认选中的样式不好看,鉴于此,有renderContent来改造iview的树组件, 效果如图 代码如下 <templat ...

  3. Java 集合详解 | 一篇文章解决Java 三大集合

    更好阅读体验:Java 集合详解 | 一篇文章搞定Java 三大集合 好看的皮囊像是一个个容器,有趣的灵魂像是容器里的数据.接下来讲解Java集合数据容器. 文章篇幅有点长,还请耐心阅读.如只是为了解 ...

  4. markdownFormat

      对文档编辑主要还是用wps,因为以前毕业论文都是用的它来编排(刚开始用wps毕业论文的时候真的是用的想吐,感觉非常不好用,而且功能太多但对于自己需要的功能又偏偏找不到),用过几次后还觉得用它编辑文 ...

  5. day6 斐波那契数列

    1.求图片中的表达式: 2.求图中斐波那契数列的值

  6. Solon 开发,六、提取Bean的函数进行定制开发

    Solon 开发 一.注入或手动获取配置 二.注入或手动获取Bean 三.构建一个Bean的三种方式 四.Bean 扫描的三种方式 五.切面与环绕拦截 六.提取Bean的函数进行定制开发 七.自定义注 ...

  7. ctf--web刷题记录 ACTF2020back up file 、极客大挑战2019php、secret file

    ACTF2020back up file backup file指的是备份文件,一般备份文件的后缀有".git" .".svn"." .swp&quo ...

  8. Android学习笔记4

    activity配置文件 //AndroidMainifest.xml <?xml version="1.0" encoding="utf-8"?> ...

  9. Vue.use()用法

    通常我们引入一个第三方组件形式的插件进来时,我们在main.js里面需要Vue.use('该插件名字'),比如引入一个vant组件 那么我们如何自己也来尝试将自己封装的组件以Vue.use()的形式来 ...

  10. insert插入日期

    7.5.insert插入日期 数字格式化:format select ename,sal from emp: 格式化数字:fromat(数字,'格式') select ename,format(sal ...