各种优化建图(留坑)

一、线段树优化

1.

n 个点,m 个操作:

  • 1 u l r w u 向区间 [l,r] 的节点连长度为 w 的边;

  • 2 u l r w 区间 [l,r] 的节点向 u 连长度为 w 的边;

  • 3 x y l r w 区间 [x,y] 的节点向区间 [l,r] 的节点连长度为 w 的边。

1n 的最短路。

  • n,m105

直接暴力连可使边数达到 O(n2m)

使用线段树优化,将线段树上每一个节点当成这一段区间。

建两颗线段树 ABA 中父亲向儿子连长度为 0 的边,B 中儿子向父亲连长度为 0 的边,二者共用叶子节点,叶子节点编号为 1n

  1. uA 上构成 [l,r] 的节点连长度为 w 的边;
  2. B 上构成 [l,r] 的节点向 u 连长度为 w 的边;
  3. 建一个虚点,B 上构成 [x,y] 的节点向虚点连长度为 w 的边,虚点向 A 上构成 [l,r] 的节点连长度为 0 的边。

这样可将边数降至 O(mlogn+n),点数为 O(n+m) 级别,用二叉堆实现的 Dijkstra 可做到 O(mlog2n)

CF786B Legacy(模板,最短路)Code

2.

P5025 [SNOI2017]炸弹

(注意 xi 已经排过序了)

对于每一个炸弹,使用 lower_boundupper_bound 算出它能引爆的炸弹编号范围,与上题一样用线段树连边。

随后 Tarjan 缩点,并顺便维护每个强连通分量内能引爆的编号的左右端点 li,ri,那么只要引爆强连通分量内的任意一个节点,这一段区间内都会被引爆,因为强连通分量内部可以全部互相引爆。

最后再对缩点后的图进行 Dfs,当节点 u 指向节点 v 时,有

lumin(lu,lv)rumax(ru,rv)

原因是 u 爆炸可以引爆 v

对于炸弹 i,如果它属于强连通分量 u,则引爆 i 会导致 rulu+1 个炸弹爆炸。

Code

3.

P3588 [POI2015] PUS

注意题目规定数的范围是 [1,109]

由于 ai 是正整数,所以由

ax>ay

axay+1

这就是一个差分约束了,使用拓扑排序解决(可以判环),首先照抄线段树区间连边(k 个大的数将 [l,r] 分成若干段,分段处理,大的与小的分别连虚拟点),然后令 dpu 表示节点 u 的最小值,初始值所有均为 1(范围内最小值),如果数已知则为已知值。

当节点 u 指向节点 v 时,

dpv=max(dpv,dpu+disu,v)

无解有 3 种情况:

  1. 出现环(用 vis 值判);
  2. 超出范围;
  3. au 有已知值,但 dpu>au

注意最后只判断叶子节点(即节点 1n,区间长度为 1 的节点)。

Code

二、 前后缀优化

1.

n 个点,m 个操作:

  • 1 u l r w u 向区间 [l,r] 以外的节点连长度为 w 的边;
  • 2 u l r w 区间 [l,r] 以外的节点向 u 连长度为 w 的边;
  • 3 x y l r w 区间 [x,y] 以外的节点向区间 [l,r] 以外的节点连长度为 w 的边。

1n 的最短路。

  • n,m5×105

线段树是 O(mlog2n) 的,过不去。

区间 [l,r] 以外 相当于 前缀 [1,l1]与后缀 [r+1,n]

新建 n 个点 prei 表示前缀 [1,i],再新建 n 个点 sufi 表示后缀 [i,n]

prei 分别向 iprei1 连长度为 0 的边,从 sufi 分别向 isufi+1 连长度为 0 的边。

  1. uprel1sufr+1 连长度为 w 的边;
  2. prel1sufr+1u 连长度为 w 的边;
  3. prex1sufy+1 分别向 prel1sufr+1 连长度为 w 的边。

点数为 O(n) 级别,边数为 O(n+m) 级别,Dijkstra 可做到 O((n+m)logn),足已通过。

2.

P6378 [PA2010] Riddle

2SAT 解决,每个点有选与不选两种,用 uu 表示。

以下连一条边 uv 指连双向边, u 符合则 v 必定符合,v 不符合则 u 必定不符合(在图中连 2 条边 (uv),(vu))。

由于原图中一条边 (u,v) 的两个端点至少选一个,所以要连边 uvu 不选则 v 必选,v 不选则 u 必选),注意不能是 uv 连边,因为是 至少 选一个。

代表前缀 [1,i] 的点 prei 表示在该部分中前 i 个点是否有被选的。

连边:

aipreaipreaipreai1preai1ai

然后跑 Tarjan 并判断即可。

Code

3.

CF1215F Radio Stations

仍然是 2SATuu 分别表示电站 u 开不开。

至少一个就是 uv,至多一个则是 uv

新建立 2(m+1) 个点,分别表示当 k0mfk 是否成立,记为 ai

对于一个电站 u,连边:

ualu1uaru

跑完 Tarjan 后进行判断无解就不说了。

belu<belu 时,说明电站 u 是开的,电站个数加一;

belak1<belak1belak<belak 时,说明 f>k1fk,那么 k 就是其中一个满足条件的 f,输出。

最后注意 f 是不能取 0 的,处理方法是连边 a0a0,这样保证了 f0 是一定不符合的,否则会出现矛盾。

Code

posted @   mango09  阅读(92)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
-->
点击右上角即可分享
微信分享提示