Live2D

Solution Set -「LOCAL」冲刺省选 Round XIII

Summary

  有一说一,虽然我炸了,但这场锻炼心态的效果真的好。部分分聊胜于无,区分度一题制胜,可谓针对性强的好题。

  A 题,相对性签到题。这个建图确实巧妙,多见见就好。

  B 题,小常数暴力卡常,证了复杂度就是正解,这……

  C 题,写了个伪解 ha 了差不多一个小时才 ck 掉,浪费了很多时间,策略问题啊。

Solution

A 一般图带权多重匹配

  给定 {an}{cn×n},每次操作取一对 (i,j),令 aiai1,ajaj1,代价为 ci,j。求使 {an} 全为 0 的最小代价。

  n50ai100k:=i[2ai]8


  这个 k 的限制一看就是 NPC 的问题的弱化,这提示我们从 i,2ai 的情况入手。对于每个使所有 ai=0 的策略,其选择方案可以看做 n 个结点间的连边方案,结点 i 的度数为 ai2ai,那么我们自然有办法对每条边定向,使得每个点出度入度相等。

  反过来,人为规定:加入 iai 条有向边,使得点 i 的出度和入度都为 ai2,因此可以得到费用流模型:

  • i 对应结点 i1,i2,连接 S,i1,ai2,0i2,T,ai2,0
  • i,j,连接 i1,j2,+,cij

这个网络的最小费用就是答案!

  考虑奇数,其实也没啥事了,(kk/2) 枚举多出来的 1 放在 i1 还是 i2,相当于枚举多出来的是一个入度还是出度。最终复杂度为 O((kk/2)Dinic(2n+2,n+n2))

B 排序

  (略有简化。)给定一棵含有 n 个结点,以结点 1 为根的树。每个叶子有一个非空取值集合,你需要构造叶子的取值方案,使得存在一种 DFS 方法使遍历到的叶子的值单调递增。若有解,输出取值方案及 DFS 方案。

  令 mii 的取值集合大小(若 i 非叶,则 mi=0),k 为结点最多拥有的孩子数量,则 n,imi105k8。保证取值集合所有元素互不相同。


  有一个非常显然的暴力:令 f(u) 表示 u 子树内极小取值区间集合,定义合法取值区间 [l,r] 极小当且仅当不存在合法取值区间 [l,r],使得 llrr。转移时全排列枚举孩子顺序以及左端点,一路 lower bound 过去得到对应右端点,最后删掉不极小的取值区间。

  进一步,这个全排列过程可以优化为:枚举第一个孩子及其左端点,状压其余孩子求最小右端点。设 u 的孩子们的 f 集合大小为 s1,s2,,sk,则转移 u 的复杂度为 O((isi)2k1(ilogsi)),其中 log 是转移内部的 std::lower_bound,也许可以优化掉叭 awa;转移复杂度之和是算法瓶颈。

  加一个优化:若 u 只有一个孩子,作常数的处理之后直接继承这个孩子的 f 信息。

  好,现在我们证明这个暴力是对的(?!)

  考虑某片叶子 l 处的取值集合 S,我们称 xSucontributor,当且仅当 xf(u) 内某个区间的左端点。对于 l 的祖先 u,定义 Su={xSx is ucontributor},初始时自然有 Sl=S。现对于 l 的拥有至少两个孩子祖先 v,及 v 的父亲 u,考虑 Sv 变到 Su 的过程:

  显然 SuSv,显然 x,ySuxy,构成 [x,x]f(u) 的转移区间序列 X=[x,x1],[x2,x3], 与构成 [y,y]f(u) 的转移区间序列 Y=[y,y1],[y2,y3], 必然满足:[x2,x3][y2,y3]

  这一点表明,若 vcontributor 想要成为 vcontributor,就必然需要 v 的一个独一无二的 contributor 给予“支持”(注意并不一定消耗这个 contributor)。

  现在,我们抛却所有题目本身的性质,只考虑这个弱化限制下的 contributor 总量:设 u 的孩子们 v1,v2,,vk 给到 u 的 contributor 数量是 c1,c2,,ck,不妨设 c1c2ck,根据我们的 contributor lemma,我们知道

cki=1k1|f(vi)|.

因而

|f(u)|=i=1kcimin{2i=1k1|f(vi)|,i=1k|f(vi)|}.

  最后,把问题放在全局,令 cu 表示 u 对父亲的 contributor 数量,特别地,c1=|f(1)|;令 su 表示 u 的子树内所有叶子取值集合大小和,那么

ucu=u is not a leaf|f(u)|.

根据结论:

ucu|f(1)|+2uvson(u)vargmax{|f(w)|wson(u)}|f(v)||f(1)|+2usv=O(nlogn).

(假定 n,m 同阶。可以发现第二步表述的就是 DSU on Tree 的复杂度。)

  因此,我们得到该算法的一个复杂度上界:O(k2k1nlogn)(crashed 指出 std::lower_bound 的确可以优化掉)。算出来大概是 1.7×109,不过至少摆脱了“暴力 n2”的范畴;况且 k2k1 很难在每个点取满,所以还是比较令人信服的算法。(

C 传染

  给定一棵含有 n 个点的有边权的树,结点 u 爆炸会使与其距离不超过 ru 的结点爆炸。求至少要人为起爆多少个结点才能使所有点爆炸。

  n3×105


  点分治 + Two-pointers 优化建图。每次考虑跨过点分中心 x 的爆炸传导路径,求到结点们分别按“引爆其他子树的能力”和“被其他子树引爆的能力”排序的序列 S,T,发现每个 sS 连向 T 的前缀;si 能影响的结点是 si+1 能影响的子集。建虚点优化建图跑 Tarjan 即可。

  点数和边数都是 O(nlogn) 的,不过排序序列造成了瓶颈 O(nlog2n)。不考虑 Radix Sort 等不讲武德的东西,猜测可以用边分树 + 归并处理两个序列做到 O(nlogn)

posted @   Rainybunny  阅读(135)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示