UOJ pjudge LOJ 试题乱做 Part2

啊, 这个 \(\text{Part}\) 因为刚打完 \(unr6\) , 所以前 \(5\) 题都会是 \(unr6\) 的题, 为什么不是前 \(6\) 题呢, 因为第六题现在有点做不得.


\(\text{【UNR \#6】面基之路}\)

\(\color{green}{\text{[EASY]}}\)

不难发现最终所有点会走到一个地方, 所以一定是所有点到最终位置的最短路的最大值.

发现 \(k\) 很小, 那就是 \(k\) 遍最短路了, 最终位置在点上是好求的, 麻烦的是在边上, 暴力的做法是 \(\mathcal{O}(2^k)\) 枚举从边的两端哪里进入.

考虑如何优化, 每一侧其实只用关注最晚进入的点, 那按照左侧的大小从小到大排序, 另右侧按降序, 可以发现, 左侧一定是选了一个前缀, 右侧一定是选了一个后缀, 最后注意情况是否合法需判断最后的终点是否在边上.

时间复杂度 \(\mathcal{O}(kn\log{n}+mk\log{k})\) .


\(\text{【UNR \#6】机器人表演}\)

\(\color{blue}{\text{[NORMAL]}}\)

其实知道思路之后, 我觉得我再来一次想得出来, 但我确实不擅长这种不用关注具体字符串的 \(dp\) .

考虑一个最终串是否能删掉一个原串子序列, 最终得到一个合法括号序列.

尝试贪心构造, 每次尝试把一个位置放在原串中, 如果不能就放在合法括号序列中, 如果括号序列变得不合法, 那就拿走原串一个尽量短的后缀, 给括号序列.

为什么是尽量短呢, 这是为了避免算重, 自己意会一下, 证明看原题解.

\(f_{i,j,s}\) 表示做到了前 \(i\) 位, 往原串放了 \(j\) 个, 此时括号序列的前缀和为 \(s\) 的方案数.

\[\begin{align*} &f_{i,j,s}\rightarrow f_{i+1,j+1,s} &\\ &f_{i,j,s} \rightarrow f_{i+1,j,s+1} &,\; j+1\;位置上为右括号\\ &f_{i,j,s} \rightarrow f_{i+1,j,s-1} &,\; j+1\;位置上为左括号,\; 且\;s-1\geqslant 0\\ &f_{i,j,s} \rightarrow f_{i+1,k,0} &,\; j+1\;位置上为左括号,\; 且\;s-1 < 0 \end{align*} \]

时间复杂度 \(\mathcal{O}((n+t)nt)\) .


\(\text{【UNR \#6】稳健型选手}\)

\(\color{green}{\text{[EASY]}}\)

为什么没做出来呢, 这个是真得反思啊, 这题是真不难啊.

首先不难得到一个 \(\mathcal{nq\log{n}}\) 的反悔贪心做法, 再发现, 正着做和反着做反悔贪心都可以, 考虑猫树.

如果直接猫树时间复杂度是对的 \(\mathcal{O}(n\log^2{n}+q\log{n})\) , 但是空间复杂度寄了 \(\mathcal{O}(n^2\log{n})\) .

考虑优化, 现在我们相当于是要维护 \([l,mid]\) 的后缀取了哪些数和 \([mid+1,r]\) 的前缀哪些数没取, 合并 \([x,mid]\)\([mid+1,y]\) 的时候就会是 \([x,mid]\) 中原本选了的一些数不选了, \([mid+1,y]\) 中的一些数原本没选现在选了.

设左区间中发生变化的集合为 \(S\) , 右区间发生变化的集合为 \(T\) , 显然要有 \(|S|=|T|\) , 和 \(\max{S} < \min{T}\) , 所以按值排序后 \(S\) 是一段前缀, \(T\) 是一段后缀, 所以我们需要找到最大的 \(k\) 满足, 左边第 \(k\) 小小于右边第 \(k\) 大.

满足排序和二分的单 \(\log\) 数据结构, 不难想到主席树维护, 于是就做完了, 写的时候写整体二分即可.

时间复杂度 \(\mathcal{O}(n\log^2{n}+q\log{n})\) , 空间复杂度 \(\mathcal{O}(n\log{n})\) .


\(\text{【UNR \#6】小火车}\)

\(\color{blue}{\text{[NORMAL]}}\)

怎么说呢, 看了眼做法发现没那么难, 但是就是没想到.

原题等价于找出两个不相交的子集, 使得集合元素和相等, 又等价于找出两个不相同的子集, 使得集合元素相等.

考虑抽屉原理, 我们考虑有 \(p\) 个桶, 编号为 \(0\)\(p-1\) , 一共放了 \(2^n\) 个元素, 这样至少有一个桶装了两个元素, 我们的目标就是找到这个桶.

更进一步, 对于一个桶的区间 \([l,r]\) , 如果这些桶中装了超过 \(r-l+1\) 个子集, 那有区间中一定存在目标桶, 令 \(s_{l,r}\) 表示区间 \([l,r]\) 中一共装了多少个子集.

显然如果 \(s_{l,r}\) , 那么对于 \(k\in[l,r)\) , \(s_{l,k}>k-l+1\)\(s_{k+1,r}>r-k\) 中至少有一个成立, 因此我们只需要快速计算出 \(s_{l,r}\) , 就可以通过二分快速找到目标位置.

计算 \(s\) , 我们考虑 \(meet \; in \; middle\) , 把数分为两侧, 计算出子集和并排序, 每次询问双指针即可.

时间复杂度 \(\mathcal{O}(2^{\frac{n}{2}}\log{p})\) .


\(\text{【UNR \#6】神隐}\)

\(\color{blue}{\text{[NORMAL]}}\)

好像还挺自然的.

我们为了能区分所有边, 那一定是对于任意两个边, 在某一次询问中, 出现了第一条边就不能出现第二条边, 或出现了第二条边就不能出现第一条边.

考虑这样一种构造, 选取 \([0,2^{lim})\) 中二进制中 \(1\) 的个数为 \(\dfrac{lim}{2}\) 的所有数作为编号赋给所有边, 其中 \(lim\) 为询问次数限制.

进行 \(lim\) 次询问, 对于第 \(i\) 次询问, 我们对于新的编号中二进制中第 \(i\) 位为 \(1\) 的边作为需要询问的边.

询问完开始考虑怎么通过我们的询问, 构造出这棵树, 我们考虑删叶子.

一个点是叶子的时候, 度数为 \(1\) , 此时其在一半的询问中为一个单独的点的连通块, 一个点在另外一半不是孤点的时候询问所在的连通块, 一定包含了其父亲, 也容易说明些连通块的交集中只有它的父亲.

时间复杂度 \(\mathcal{O}(n\log{n})\) .


\(\text{【PR \#7】大凯的疑惑}\)

\(\color{blue}{\text{[NORMAL]}}\)

好牛逼啊这题, 反正我觉得是个正常 \(OIer\) 就不应该想到, 但对于 \(MOer\) 我估计是有手就行.

我们尝试化简原式,

\[(a+d)^k-a^k = \sum_{i=0}^{k}{\binom{k}{i}d^ia^{k-i}}-a^k \\ =\sum_{i=1}^{k}{\binom{k}{i}d^ia^{k-i}} \]

\(f_i=\binom{k}{i}d^i\) , 因为是对于任意正整数 \(a\) 成立, 所以不妨只考虑 \(a=1\) , 列出 \(f\) 的前后几项, \(f_1=kd,f_2=\frac{k(k-1)d^2}{2},\dots,f_k=d^k\) .

不难发现答案的所有质因子一定是 \(d\) 的质因子, 对 \(d\) 的每个质因子分别考虑, 设 \(C(x)\) 表示 \(x\)\(p\) 的次数.

一个小巧的 \(Lemma\) , 当 \(i \leqslant p^{C(k)}\) 时, \(C(\binom{k}{i})=C(k)-C(i)\) .

\(Proof\) : 显然有 \(C(k-t)=C(k)-C(t),1 \leqslant t \leqslant p^{C(k)}\) .

\[C(\binom{k}{i}) = C(\frac{k(k-1)\cdots(k-i+1)}{i!})=C(k(k-1)\cdots(k-i+1))-C(i!)\\ =C(k)+C(k-1)+\dots+C(k-i+1)-C(1)-C(2)-\dots-C(i)\\ =C(k)+C(1)+\dots+C(i-1)-C(1)-C(2)-\dots-C(i)=C(k)-C(i) \]

因此有 \(C(f_i)=iC(d)+C(k)-C(i),1\leqslant i\leqslant p^{C(k)}\) . 并且由于 \(C(d)\geqslant 1\) , 不难发现 \(C(f_i)\) 大致是递增的, 即最小值为 \(C(f_1)\) , 所以对于质因子 \(p\) 的答案即为 \(p^{C(f_1)}\) .

那么最大正整数解即为 \(\gcd(d^{\infty},kd)\) .

一个特殊情况, 当 \(p=2,C(d)=1,2|k\) 时, \(C(f_2)=C(f_1)=C(kd)\) , 所以答案应多乘一个 \(2\) .

要写高精很恶心人.


\(\text{【PR \#7】道路重建}\)

\(\color{green}{\text{[EASY]}}\)

最开始想错了, 以为直接就是每个求出最小生成树然后选最小的 \(n-1\)\(a_i\) 加起来, 然后觉得不可能这么简单, 思考了很久为什么不对.

后来发现实际上也差不了多少.

考虑有什么时候不是那种情况, 求最小生成树的时候, 如果一个边连起来可以使得两个有枢纽站的点合并成一个连通块, 那这个边可能是不用连的, 但如果不是, 那这条边则一定是要连的.

预处理出来, 现在相当于每个点都是枢纽站, 考虑再一次模拟 \(Kruskal\) 的过程, 也就是选哪些 \(a_i\) , 实际上最开始的考虑是对的, 只有一个 \(a_i\) 是不被选择的.

从小到大考虑 \(a_i\) , 不妨设 \(\arg{\min\{a_i\}}=1\) , 且 \(b_1<b_2\) , 显然城市 \(1\) 是城市 \(2\) 的超集, 因此我们直接二分出之前求最小生成树时第一个大于 \(a_i-b_i\) 的不边, 在此之后合并两个都存在枢纽站的连通块的边均不连, 选择连 \(a_i\) .

时间复杂度 \(\mathcal{O}(n\log{n})\) .


\(\text{【Goodbye Yiwei】新年的腮雷}\)

\(\color{blue}{\text{[NORMAL]}}\)

emmm, 为什么又没想到呢, 反思.

先二分答案, 逆向思维, 考虑拆炸弹, 问题变为, 是否存在一种拆分方案, 能从一个 \(x\) 的腮雷开始拆成 \(n\) 个, 设这个序列为 \(c_1,c_2,\dots,c_n\) , 使得存在一个匹配 \(p_i\) , 使得 \(c_{p_i}\geqslant a_i\) .

也就是说, 给出腮雷集合 \(S\)\(T\) , 允许在 \(S\) 中拆雷, 最终使得存在上述匹配方案. 问题最初 \(S\) 中只有 \(x\) , \(T\) 中有 \(a_i\) .

如果 \(|S|=|T|\) , 则将 \(S\)\(T\) 从小到大排序, \(S\) 均大于等于 \(T\) 中的对应元素则可行, 否则不可行.

否则, 如果 \(S\) 为空则不可行.

否则, 设 \(S\) 中的最大元素为 \(s\) , \(T\) 中的最大元素为 \(t\) , 不妨设 \(b\) 中的最小元素为 \(b_1\) , 根据 \(s-b_1\) 的大小关系, 我们采取以下策略.

  • \(s-b_1<t\) , 则在 \(S\) 中找到最小的大于等于 \(t\) 的元素 \(s_0\) , 并将 \(s_0\)\(t\) 组成匹配关系, 即删除, 问题 \((S,T)\) 的可行性与 \((S\setminus {s_0},T\setminus {t})\) 的可行性等价. 如果找不到 \(s_0\) , 则问题 \((S,T)\) 不可行.
  • \(s-b_1 \geqslant t\) , 则将 \(s\) 拆分成 \(m\) 个腮雷, 即问题 \((S,T)\) 的可行性和问题 \((S\setminus{s}\cup\{s-b_1,s-b_2,\dots,s-b_m\},T)\) 的可行性相同.

正确性,

  • 对于前者, 由于 \(t\) 不能与 \(S\) 中某个拆分得来的元素匹配, 因为最大的元素拆分都无法满足, 所以只能与 \(S\) 中的某个元素匹配, 显然只要选择最小的一个可行的元素即可.
  • 对于后者, 由于 \(|S|<|T|\) , 所以一定是有元素要被拆分的, 假如拆分的不是 \(s\) , 则假设拆分的元素为 \(s_1\) , 且 \(s\) 最终和 \(t_1\) 匹配, 那么剩下的元素为 \(s_1-b_1,s_1-b_2,\dots,s_1-b_m\) , 如果我们拆 \(s\) , 将 \(t_1\)\(s-b_1\) 匹配, 剩下的元素为 \(s_1,s-b_2,\dots,s-b_m\) , 对应大于之前的每个元素.

对于前者的, 由于 \(T\) 中只有 \(n\) 个元素, 所以只会进行 \(n\) 次, 对于后者, 每次发生之多让 \(S\) 增加 \(m-1\) 个元素, 之多进行 \(\frac{n-1}{m-1}\) 次.

\(multiset\) 维护两个集合, 时间复杂度 \(\mathcal{O}(n\log{n}\log{V})\) .


\(\text{【PER \#2】简单数据结构}\)

\(\color{green}{\text{[EASY]}}\)

\(u_x+v_x \geqslant u_y+v_y\) 当且仅当 \(u_x-u_y \geqslant v_y-v_x\) , 以 \(u_x-u_y\)\(v_y-v_x\) 作为下标, 线段树维护最小的 \(U\) 中的二元组和最小的 \(V\) 中的二元组以及答案即可, 时间复杂度 \(\mathcal{O}(n\log{n})\) .


\(\text{【PER \#1】捉迷藏}\)

\(\color{green}{\text{[EASY]}}\)

好耶, 为数不多的自己想出来的 \(pjudge\) 题.

我们先考虑一次询问的时候, 先以询问的 \(x\) 为根, 对于所有距离 \(x\)\(d\) 的点我们视作关键点.

首先发现 \(B\) 最理想的情况一定是走到树的直径上距离它最远的点然后在那等着.

那么我们肯定要往最长链上走上 \(\lfloor\frac{d-1}{2}\rfloor\) 步, 这样子保证不会相遇, 并且还有让 \(A\) 跟着走的余地, 并且此时 \(A\) 一定在 \(y\) 的某个有关键点的子树中, 其中 \(y\)\(B\) 往最长链上走 \(\lfloor\frac{d-1}{2}\rfloor\) 步到的位置, 如果不在就不是最坏情况了.

这个时候 \(B\) 有两种选择, 一种是走回父亲结点, 然后再往最远的点跑. 还有一种是往某个不存在关键点的子树走, 走到最远的点, 不存在关键点即为以 \(x\) 为根时深度小于 \(d\) .

可以发现, 这样走一定是 \(A\) 追着 \(B\) 跑. 所以可以直接分别以两个直径的端点为根, 倍增跳祖先简单维护即可.

时间复杂度 \(\mathcal{O}((n+q)\log{n})\) .


有意思的题目增加了, 但是为什么就高二了, 时间过得好快啊.

posted @ 2022-09-26 21:10  Lonely923  阅读(79)  评论(0编辑  收藏  举报