2024.7.18 test

A

给定 \(n\) 个 01 串 \(s_1\sim s_n\),构造字典序最小的排列 \(p_1\sim p_n\),使得串 \(T=s_{p1}+s_{p2}+...+s_{pn}\) 满足对于所有 \(i\bmod m=b\)\(T_i=1\),其它为 \(0\),或报告无解。\(n\le 1e5\)\(\sum|s|\le 1e6\)\(\sum |s|\)\(m\) 的倍数。

一个 \(s_i\) 可以看做是这样的:前面若干 \(0\),中间有多少个 \(1\) 都相当于只有一个 \(1\),后面若干 \(0\)
我们设当前已经填了总共 \(len\) 长度的 \(s\),注意到 \(len\) 同余 \(m\) 的点都是等价的,
我们构建 \(n\) 个点,代表当前 \(\bmod m\) 的值,每个 \(s_i\) 都代表存在只有一条 \(u\to v\) 的边,仅有此时合法。
于是跑欧拉回路,需要做到字典序最小。

B

\(n\) 件商品,利润为 \(v_i\),存在未知的 \(w_i\) 满足 \(w_i\in[l_i,r_i]\),你要选若干件商品出来,使得在所有 \(w\) 的取值里, \(\dfrac{\sum w_iv_i}{\sum w_i+w_0}\) 最小值最大。

可以看做 \(v_0=0\) 是必选的。我们相当于做一个加权平均。那么我们要想其最大,肯定从 \(v\) 大的开始取。
我们考虑的是最小值最大,那么对于大的 \(v_i\)\(w_i\) 肯定是取到 \(l_i\)
当我们取到 \(v_j\),现在的加权平均为 \(mid\),若此时 \(v_j<mid\),那么跟 \(v_j\) 做平均无论如何都会减少 \(mid\)
所以我们此时就不取了。可以二分找到这个 \(j\),用数据结构维护一下后缀和即可。

C

在二维网格上有 \(n\) 个点,你要选择一个位置和 \(k\) 个点,使得这 \(k\) 个点到这个位置的和最小。\(n\le 1500\).

容易看出我们选择的位置是这 \(n\) 个点的所有 \(x,y\) 拿出来的交点。共 \(O(n^2)\) 个。
我们可能无法省去枚举这 \(O(n^2)\) 个点了,我们考虑优化计算前 \(k\) 近的点。
我们先固定一维 \(y\),递推 \(x\) 这维,随着我们的移动,左边的点距离会加,右边的点距离会减。
我们用堆维护左边和右边两个集合,每次右边集合中的一些点会移动到左边,
我们要在左边找前 \(k_1\) 大的,右边找前 \(k_2\) 大的,\(k=k_1+k_2\),且总和最小。
不妨维护两个堆,设从右边移动了 \(c\) 个点到左边,那么 \(k_1,k_2\) 的变化量是 \(O(c)\) 的,双指针维护。

D

你要把字符串 \(B\) 插入 \(A\) 的某个位置,使得子串 \(P\) 出现次数最多。\(n\le 10^5\)

设插入后的序列 \(S=L+B+R\)\(P\) 完全在 \(L,B,R\) 里面的,这个可以简单计算。
\(P\) 同时在 \(L,B\) 里面,我们先标记所有满足 \(P[x:]=B[:x]\),这代表 \(P\)\(x\) 后可以跟 \(B\) 匹配上。
我们现在要看 \(L\) 中能跟 \(P\) 接上的有多少,我们不妨做 kmp 做到 \(i\),设当前 \(P\) 匹配到 \(j\)
那么 \(j\) 不断跳 border,看被标记了有多少个即可,在 fail 树上处理。
\(P\) 同时在 \(B,R\) 的话同理。
最难的是 \(P\) 同时在 \(L,B,R\) 里面。两棵 fail 树,二维数点。

posted @ 2024-07-18 20:07  s1monG  阅读(11)  评论(0)    收藏  举报