Live2D

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

\(\mathscr{Summary}\)

  前期节奏太懒散,后面发现 C 题是水题都没时间写,提起精神来啊!

  A 题卡得比较久,对线性基的理解不够深刻,思来想去半天才把转移系数调对。B 题也卡,走起来就想“怎么优化”而没有深入去研究“求的什么”。C 题哈哈哈哈倍增长剖一个个伪,最后祭了一发暴力,明明那么蠢(而且貌似才做过)的点分的说。

\(\mathscr{A}-\) 神必的集合

  给定 \(m\) 对形如 \((x_i,y_i)\) 的限制,求 \(\{0,1\}^n\) 里有多少个 \(S\),满足 \(\forall x,y\in S\)\(x+y\in S\)(加法即异或),且 \(S\) 里第 \(x_i\) 大数是 \(y_i\)

  \(n\le10\)\(m\le200\)


  按照兔子一贯的坏习惯,不区分二进制数和 \(\{0,1\}^n\) 里的向量。

  我们只需要确定 \(S\) 的基 \(\mathscr S\) 的数量,就能求出 \(S\) 的数量。对于 \(\{y_{1..m}\}\) 的基 \(\mathscr Y\),显然有 \(\operatorname{span}(\mathscr Y)\subseteq\operatorname{span}(\mathscr S)\)。另一方面,不妨把 \(\mathscr S\)\(\mathscr Y\) 规范化作上三角,也就是异或线性基求出来的那玩意儿。

  考虑若 \(\mathscr S\) 确定,比 \(y\) 小的数的数量 \(x-1\) 是如何算出来的。方便起见,令 \(x\leftarrow x-1\),显然若 \(x\) 含有 bit \(2^k\),就表明 \(\mathscr S\) 从低到高第 \(k\) 个基向量的最高 bit 被 \(y\) 包含。据此,对于任意 \(i,j\),我们能够判断 \(2^i\) 能否作为 \(\mathscr S\) 的从低到高 \(j\) 个基向量的最高 bit。

  据此,考虑 DP。令 \(f(i,j)\) 表示考虑了 bit \(2^{0..i}\),已经选择了前 \(j\) 小的基向量的方案数。当 \(\mathscr Y\) 在这一维有基向量时,这个时候我们只能当然只能 \(\mathscr Y\) 里对应位置上的基向量;否则,我们可以任意取 \(\{0,1\}^{i+1}\) 里一个不与已有的 \(j\) 个基线性相关的向量来扩展基,也可以不把 \(i\) 选入基。形式化地,令 \(c\)\(2^i\) 能否作为第 \(j\) 个基向量,那么

\[\begin{cases} f(i+1,j+1)\leftarrow^+cf(i,j), & \exist y\in[2^{i+1},2^{i+2})\in\mathscr Y\\ \begin{cases} f(i+1,j+1)\leftarrow^+ cf(i,j)\times2^{i+1-j}\\ f(i+1,j)\leftarrow^+ f(i,j) \end{cases}, & \text{otherwise} \end{cases} \]

至少可以做到 \(\mathcal O(n^2+nm)\)

\(\mathscr{B}-\) 法阵

  给定 \(\{a_n\}\) 以及 \(q\) 次询问,每次给出 \([l,r]\),求 \(\max\{a_x+a_y+a_z\mid l\le x<y<z\le r,y-x\le z-y\}\)

  \(n,q\le5\times10^5\)


  注意到在固定 \(x\) 时,若有 \(x<y_1<y_2\),且 \(a_{y_1}\ge a_{y_2}\),那么 \(y_2\)\(x\) 配对必然不如 \(y_1\) 优秀。因此,有效的 \((x,y)\) 必然在从左到右单调栈时相遇(\(y\) 弹掉 \(x\),或者 \(y\) 压入 \(x\) 的后面),这样的 \((x,y)\)\(\mathcal O(n)\) 对。

  既然 \((x,y)\) 很少,我们就去维护 \(z\)。把询问离线下来挂到左段点上,从右到左扫描 \(l\),对于每个 \(r\),维护此时 \(x\in[l,r],z\in[l+2,r]\) 的答案。放在线段树上,每次更新差不多就是区间取 \(\max\),可以做到 \(\mathcal O((n+q)\log n)\)

\(\mathscr{C}-\) 旅行

  给定含有 \(n\) 个点 \(m\) 条边的无边权无向图,点 \(u\) 有属性 \(r_u\)\(c_u\),表示对于所有 \(\operatorname{dist}(u,v)\le r_u\),可以从 \(u\) 花费 \(c_u\) 的代价走到 \(v\)。求从 \(1\) 出发到每个点的最小花费。

  \(n\le2\times10^5\)\(n-1\le m\le n+50\)\(c_u>0\)


  这个 \(m\) 范围的提示性太强了,随便拿一棵生成树,树内点分建图,树外边还是向点分一样处理跨过某个点的路径信息,记 \(t=m-n+1\),暴力做复杂度为 \(\mathcal O(n\log^2n+nt\log nt)\),可以过。

  点分部分采用 two-pointers 建图,每次拿出 \(d_u+c_u\) 最小的点,从上次指针划到的位置继续更新,不把图显式地建出来。可以做到 \(\mathcal O(n\log n+nt)\)

posted @ 2022-03-14 16:52  Rainybunny  阅读(80)  评论(0编辑  收藏  举报