题解 CF1641C - Anonymity Is Important

CF1641C - Anonymity Is Important

非常抽象,建议自己把数据放代码上跑,理解过程。

并查集的另类用法。

我们设 \(fa_i\) 去维护包含 \(i\) 的全健康区间。具体来说,对于一个区间 \([l,r]\),我们将 \(fa_{l\sim r}\) 全部都接在 \(fa_{r+1}\) 上。这样会有两个用处:

  • 如果 \(fa_i\ne i\) 那么 \(i\) 是健康的。
  • \(fa_i\) 代表包含 \(i\) 的全健康区间的最右边端点 +1。

我们再设置一个数组 \(L_i\) 代表 \(i\) 左边 至少一病区间 的左端点在哪里。如果有多个取离 \(i\) 最近的。

那么对于询问一个点 \(x\),我们就看:

  • 如果 \(fa_x\ne x\) 那么 \(i\) 没有生病。
  • \(t=fa_{x+1}\),代表右端点大于 \(x\) ,且包含 \(x+1\),的健康区间。设 \(p=L_t\) 代表,包含那个健康区间的 至少一病区间 的最左边端点。如果这个 至少一病区间 内只有 \(x\) 了(也就是 \(fa_p=x\))那么他就生病了。否则就是 N/A。

怎么修改?

如果是加入一个健康区间,那么就是不断地将 \(l\sim r\) 变成 \(r+1\) 的子孙。(实际操作中,如果枚举到 \(i\) 的时候,发现 \(i\) 已经是 \(r+1\) 的子孙,那么就可以直接结束了,保证时间复杂度。)

如果是加入一个至少一病区间,那么就更新一下 \(L_i\) 即可。

posted @ 2022-02-25 08:58  BlankAo  阅读(123)  评论(0编辑  收藏  举报