2023.11 做题纪要 #1

2023.11.4

打模拟赛,做题纪要摆一摆。

P9338 [JOISC 2023 Day3] Chorus

为了做这题把整个决策单调性的东西学了一遍,虽然最后也没用上多少吧。

首先如果存在划分数 \(\le K\) 的方案,那么一定存在 \(=K\) 的方案,那么我们就是要让最少划分数尽可能小。

先考虑对于一种固定的 AB 序列如何求出最少的划分数。考虑一个贪心的匹配方法,从前往后将每个极长 A 段与后面相应个数个 B 对应,这样就能得到最少的划分数。考虑这实际上相当于让第 \(i\) 个 A 与第 \(i\) 个 B 相匹配,并将这样的若干对 AB 划分成最少条链,使得每条链中的所有 A 都在 B 左边,定义两对 AB 之间的偏序关系为第 \(i\) 个 B 在第 \(j\) 个 A 左边,那么上述问题就是一个最少反链覆盖,根据 Dilworth 定理,这等于最长链,那么最少划分数就等于能选出的最多的两两不交的 AB 对,由于 AB 的位置都是单调递增的,这有显然的贪心做法,从前往后能选则选即可。

那么发现这个过程就可以 DP 了,考虑当前已经确定了第 \(1 \sim j\) 个 AB,选取的最后一个 B 的下一个 A 是第 \(j+1\) 个 A,那么按照贪心,下一次选择的就是第 \(j+1\) 个 A,考虑每次确定第 \(j+1\) 个 A 与 B 之间有多少个 A,这样就能确定下一次选择哪一个 A 了,假设从 \(j\) 转移到 \(i\),那么我们需要将第 \(j + 1\) 到第 \(i\) 个 A 移动到第 \(j + 1\) 个 B 的前面,那么考虑设 \(b_i\) 表示第 \(i\) 个 A 前面有 \(b_i\) 个 B,则移动次数为 \(\sum_{t=j+1}^i \max(0, b_t - j)\),可以写出 DP \(f_{i, k} = \min_{1 \le j < i} f_{j, k - 1} + \sum_{t = j + 1}^i \max(0, b_t - j)\)

发现贡献函数 \(w(j, i) = \sum_{t = j + 1}^i \max(0, b_t - j)\) 满足四边形不等式,那么答案关于 \(k\) 是凸的,具体可以看 决策单调性与四边形不等式学习笔记。于是我们可以直接 wqs 二分把第二维去掉。

然后考虑如何快速计算内层 DP,由于 \(b_k\) 具有单调性,我们可以设 \(p_i\) 为最小的 \(k\) 满足 \(b_k \ge i\),那么就可以把 \(\max\) 拆掉了,发现是一个斜率优化的形式,直接做即可。不过还有一点,就是对于 \(p_j > i\)\(j\) 这样计算贡献可能会算错(好像其实也不会影响,比较神秘),但是发现如果 \(b_i < j\) 那么你从 \(b_i\) 转移来一定是不劣的,因为权值仍然为 \(0\) 而转移点更小,所以这些地方可以直接不转移。

ABC327G Many Good Tuple Problems

我为啥上来就枚举左右部点的数量,我恼了,赛后十分钟过了。虽然我也没打吧。

考虑设 \(f_{n, m}\)\(n\) 个点 \(m\) 条边的连通二分图方案数,发现这玩意不咋好做,发现任意图黑白染色的方案数是容易求的,即 \(\sum_{i=0}^n \binom{n}{i} (i(n-i))^m\),假如设 \(f_{n,m}\) 的二元 EGF 为 \(F(x, y)\),那么考虑到每一个连通块有两种染色方案,于是任意图黑白染色的方案数实际上等于 \([\frac{x^n}{n!} \frac{y^m}{m!}] e^{2F(x,y)}\),那么有 \(e^{2F(x,y)} = \sum_{i \ge 0} \sum_{j \ge 0} \frac{x^i}{i!} \frac{y^j}{j!}\sum_{k=0}^i \binom{i}{k} (k(i-k))^j = \sum_{i \ge 0} \frac{x^i}{i!} \sum_{k=0}^i \binom{i}{k} \sum_{j \ge 0} \frac{(k(i-k)y)^j}{j!} = \sum_{i \ge 0} \frac{x^i}{i!} \sum_{k=0}^i \binom{i}{k} e^{k(i-k)y}\),而我们要计算的答案实际上就是 \([\frac{x^n}{n!} \frac{y^m}{m!}] e^{F(x, y)}\),于是令 \(G(x, y) = e^{2F(x, y)}\),我们只需要计算 \([\frac{x^n}{n!} \frac{y^m}{m!}] \sqrt{G(x, y)}\) 即可。

发现 \(G(x, y)\) 可以表示成 \(x, e^y\) 的多项式,我们把 \(e^y\) 先换成 \(z\),那么就可以暴力计算出 \(G(x,z)\) 的前 \(O(n^3)\) 项,然后开根可以 \(O(n^2)\) 开,具体利用 \(\sum_{i=0}^n f_i f_{n-i} = g_n\) 就可以直接递推计算了,那么需要循环 \(O(n^2)\) 次,每次计算长度为 \(O(n^2)\) 的卷积,那么此时我们就要计算 \([\frac{y^m}{m!}] \sum_{i=0}^{n^2} g_i e^{iy}\),直接算就行了,总复杂度 \(O(n^4 \log n)\)。注意最后要乘 \(2^m\),因为边可以随便定向。

2023.11.5

无模拟赛,所以今日摆大烂。

CF1237F Balanced Domino Placements

考虑枚举 \(a,b\) 表示有 \(a\) 个竖着放,\(b\) 个横着放,直接 DP 看起来不好 DP,我们可以先计算出行选 \(a\) 个长度为 \(2\)\(b\) 个长度为 \(1\) 的段,和列选 \(b\) 个长度为 \(2\)\(a\) 个长度为 \(1\) 的段的方案数,然后再乘一个 \(a!b!\) 就是总方案了,那么我们就变成了一维的问题。直接 DP 是 \(O(n^3)\) 的,注意到只有长为 \(2\) 的会被一开始的划分限制,那么我们先 DP 长为 \(2\) 的,然后计算时组合数选一下长为 \(1\) 的就行了,复杂度 \(O(n^2)\)

2023.11.6

awawawawawawawawa

P7217 [JOISC2020] 収穫

可以发现让员工去摘苹果是没有前途的,我们让苹果去摘员工

那么发现时间限制其实就是一个苹果在两次给员工贡献之间至少有 \(C\) 的时间间隔,那么每个苹果之间的贡献就是独立的,而发现一个苹果在给一个员工贡献后,下一次贡献的员工是固定的,这可以预处理出来。

那么我们给员工建一张图,每个员工连向当苹果给他贡献后,下一个贡献的员工,那么这样就连出了一个内向基环森林,那么问题就变成了,每个苹果在某一时刻开始从这个内向基环森林上走,询问某一时刻一个点被经过了多少次。

显然不在环上的点最多被每一个苹果经过一次,那么我们可以将环上的点与非环上的点分开考虑。

设查询 \((T, x)\) 为询问 \(T\) 时刻经过 \(x\) 点多少次,

对于非环上的点,设 \(dis_u\)\(u\) 点到根的路径长度,\(t_i\) 为第 \(i\) 个苹果第一次碰到的员工,\(d_i\) 为第一次碰到员工的时间,那么查询就是查询有多少 \(t_i\)\(x\) 子树内,且 \(dis_{t_i} - dis_x \le T\),即 \(dis_{t_i} \le T + dis_x\),这就是一个二维数点,直接做即可。

对于环上的点,我们对每一个环上的所有询问进行考虑。设 \(p_i\) 为第 \(i\) 个苹果碰到的第一个环上的点,\(w_i\) 为碰到 \(p_i\) 的时间,令 \(len\) 为环的长度,\(m\) 为环上点的数量,那么查询的答案就是 \(\sum_i (\lfloor\frac{T - w_i - \mathrm{dis}(p_i, x)}{len} \rfloor + 1)[T \ge w_i + \mathrm{dis}(p_i, x)]\)。记 \(pre_u\) 为环上第 \(u\) 个点到第 \(m\) 个点的距离,那么 \(\mathrm{dis}(p_i, x) = pre_{p_i} - pre_x + len[p_i > x]\),那么贡献式子就变成了 \(\lfloor\frac{(T + pre_x) - (w_i + pre_{p_i})}{len} - [p_i > x] + 1\rfloor\),令 \(val = T + pre_x\)\(q_i = w_i + pre_{p_i}\),那么发现 \(val\) 只与每次询问有关,\(q_i\) 只跟每个苹果有关,查询式子就变成了 \(\sum_i (\lfloor\frac{val - q_i}{len}\rfloor + 1 - [p_i > x])[val \ge q_i + [p_i > x] len]\)

发现后面那个不等式与 \([p_i > x]\) 有关,很烦人,但是注意到前面那个式子一定 \(\ge 1\),所以即使把 \(val\) 的下界往下放 \(len\) 也不会改变结果,所以我们可以直接把 \([p_i > x]\) 的限制去掉,也就是改成 \(\sum_i (\lfloor\frac{val - q_i}{len}\rfloor + 1 - [p_i > x])[val \ge q_i]\)。然后向下取整很恶心,注意到 \(\lfloor\frac{a-b}{c}\rfloor = \lfloor\frac{a}{c}\rfloor - \lfloor\frac{b}{c}\rfloor - [a \bmod c < b \bmod c]\),那么我们就可以把它拆开,得到 \(\sum_i (\lfloor\frac{val}{len}\rfloor - \lfloor\frac{q_i}{len}\rfloor - [a \bmod c < b \bmod c] + 1 - [p_i > x])[val \ge q_i]\)。然后这个式子显然可以二维偏序求,直接做即可。

2023.11.7

owowowoowowowowowo

这几天要听信息学考课,摆摆摆摆摆摆。

我怎么这么摆摆摆摆摆。

模拟赛疑似有点摆烂了,弱智题不会,会做的题也没写出来。

P5538 【XR-3】Namid[A]me

模拟赛题。jjdw 本来想给我看离散对数题,然后一翻就翻到了今天模拟赛原题。

但是我写的做法很麻烦,场上口胡完了就摆了,下午才写。

首先对于前缀按位与存在单调性,且容易发现不同的值仅有 \(O(\log V)\) 个,那么对于序列上的问题,我们就可以对于每一个后缀,找出不同的 \(O(\log V)\) 种值,然后直接计算答案即可。找的过程可以记录每一个二进制位的第一个 \(0\) 的位置,那么这些位置就是所有可能的不同的值。发现快速幂很差,不过注意到模数很小,所以我们可以直接离散对数 \(O(1)\) 求解。

放到树上,注意到叶子数很少,那么我们考虑对这棵树进行链剖分,那么链数就仅有 \(O(d)\) 条。同一条链上就是序列的情况,直接做即可,不同链之间可以直接枚举所有链对,然后注意到两条链不交,那么可以直接处理出两条链上的前缀不同 \(O(\log V)\) 种按位与,然后再 \(O(\log^2 V)\) 暴力合并起来,这部分复杂度 \(O(d^2 \log^2 V)\),这样就得到了总复杂度 \(O(n \log V + d^2 \log^2 V)\) 的做法。

实际上有上述观察之后,考虑维护出每个点到子树内所有路径的不同的按位与结果,容易发现这样的结果只有 \(O(d \log V)\) 种,每次暴力合并两个子树,合并的复杂度显然不会超过 \(O(d^2 \log^2 V)\),所以直接暴力做就有极简单的 \(O(nd \log V + d^2 \log^2 V)\) 了。

2023.11.8

o.o

P9058 [Ynoi2004] rpmtdq

早就看过的题,lxl 讲课 的题,今天才写。题解就不写了,卡常卡了半天,主要就是找支配对的时候不需要对于右边的点找左边的点的前驱后继,直接找所有的点的前驱后继就可以,因为如果前驱是同侧的,那么同侧的前驱与异侧的前驱构成支配对,此时这个点与异侧的前驱是不成支配对的,所以不需要将左右单独维护,那么其实就可以单调栈做找前驱后继的部分了,或者直接写 set 卡卡常也能卡过去。还有就是前缀 \(\max\) 别写线段树,树状数组就完了。

2023.11.10

('v')

CF1110H Modest Substrings

题目实际上就是要求找出一个字符串使得 \([l, r]\) 内的所有字符串的出现次数最多,如果我们对 \([l, r]\) 中的所有字符串建出一个 AC 自动机,那么这就是一个平凡的 AC 自动机上 DP 的问题了。

考虑经典东西,就是 \([l, r]\) 内的所有数插入 Trie 内后,一定是有若干棵满 10 叉树,如果把这些满 10 叉树去掉之后,剩下的点数为 \(O(|\Sigma| \log r)\) 级别的。

那么我们可以对删掉这些满 10 叉树后的 Trie 建出 AC 自动机,然后单独计算满 10 叉树的贡献。我们考虑计算贡献时,将每个串分成两部分,前一部分是现在的 Trie 树上的节点,后一部分就是任意一个字符串,那么我们在中间的位置统计答案,即在一个满 10 叉树的根上计算出加上若干个字符后会产生的子串的贡献,这样记 \(g_{u, i}\) 表示 \(u\) 节点再添加 \(i\) 个字符后能产生的子串数,在 fail 树上对这个东西求一下链和即可,那么 DP 的形式就是每次加入一个字符后,可以贡献后面所有可能的长度的贡献,前缀和一下即可。建树的过程可以直接类似于数位 DP 的方式,记录一下是不是卡上下界,如果不卡上下界就直接给 \(g\) 统计,对于前导 \(0\) 的问题,可以钦定根节点没有 \(0\) 的转移边,如果前导 \(0\) 则不走即可。

最后就是输出方案,把最后的等于最大值的状态标记,然后建一个到被标记节点的最短路图,然后在建出的 DAG 上贪心走即可。

2023.11.13

假期结束,哈哈。

模拟赛 T4 做过,遂摆烂,口胡。

T1:分块一下就能 \(O(1)\) 修改了,复杂度 \(O(n + m)\)。(upd. jjdw 说在同一个块里就死了,算了反正随机数据还是期望线性的,问题不大)
T2:这啥,最大 XOR 路径加强版是吧。找个 DFS 树上,现在问题变成选一条路上的路径加上若干个环,树上差分一下,问题就变成了选 \(A\) 中最多两个数与 \(B\) 中任意个数的异或最大值。对 \(B\) 建个线性基,然后消下元,并且把 \(A\) 里的所有元素也消下元,这样 \(A,B\) 集合之间互不干扰了,找出 \(B\) 中异或最大值,然后再找这个值与 \(A\) 中两个数的异或最大值就行了。
T3:二分答案,然后问题变成判定是否存在方案。发现一个点的方案可以看做是从左上右下两个三角形中选一个,左下右上两个三角形中选一个,然后暴力两两判断一下是否有交,即可将限制变成 2-SAT,直接跑即可。
T4:这篇博第一道题。

P9334 [JOISC 2023 Day2] Mizuyokan 2

首先大力 DP 就是 \(O(n^3)\),注意到任意一种方案把小段缩到长度为 \(1\) 仍然满足条件,于是我们可以只记录每次选的小段的位置,这样就能 \(O(n^2)\) 了,且容易优化到 \(O(n \log n)\),但是这个做法没有什么拓展空间。

考虑分析大段的性质。首先大段有一个显然的必要条件,就是大段的和一定比段的左右两个数大,即 \(\sum_{i=l}^r a_i > \max(a_{l-1}, a_{r+1})\),我们称满足这个条件的段为好段,而最优方案下小段长度为 \(1\),于是上述条件就是一个充分条件。但是小段长度不一定等于 \(1\),不过我们可以猜测,小段长度不等于 \(1\) 时,上述条件仍然是充分条件。

证明很简单,考虑左右两个段 \([l_1, r_1], [l_2, r_2]\),如果有 \(a_{r_1 + 1} < a_{l_2 - 1}\),那么将 \(l_2\) 拓展到 \(r_1 + 2\) 显然仍然满足条件,否则将 \(r_1\) 拓展到 \(l_2 - 2\) 仍然满足条件。对于最靠左与最靠右的段,我们假设最靠左的段 \([l, r]\),右边同理,那么如果 \(a_1 < a_{l - 1}\),那么把 \(l\) 拓展到 \(2\) 显然符合条件,否则可以在左面新加一段 \([1, l - 1]\),这样也能够符合条件。也就是说,任意一种好段的划分,都可以找到一种合法方案的划分,那么我们只需要考虑找出最大的好段划分即可,这显然是等于答案的。而这个问题有很简单的贪心方式解决,对于右端点从左往右扫,如果左端点大于等于上一个右端点 \(+2\) 那么就选这个段。而这个做法就很好拓展了。

那么考虑设 \(f(r)\) 为以 \(r\) 为右端点的最小的好段的左端点,设 \(nxt(r)\) 为最小的 \(k\) 满足 \(f(k) \ge r + 2\),答案就是从 \([l, r]\) 中某个点开始跳 \(nxt\),跳到区间外为止,最多能跳多少个点。需要特殊讨论一下开头结尾是不是长为 \(1\) 的小段,这都比较简单。那么静态区间询问就可以做了。

考虑如何修改。每次修改看起来会改变很多的 \(f(r)\),并不好修改,但是可以证明 \(nxt(r) - r = O(\log V)\),考虑从右边某个点开始向左右拓展,注意到向一边拓展时,如果 \(a_{l - 1} < \sum a_i\),那么此时就可以停止拓展,否则有 \(a_{l - 1} \ge \sum a_i\),注意到拓展后 \(\sum a_i\) 会翻倍,于是每次这样拓展都会使得区间和翻倍,那么显然翻倍 \(O(\log V)\) 次后就一定会满足条件了,所以说这样的拓展向左向右都最多进行 \(O(\log V)\) 次,于是就可以证明 \(nxt(r) - r = O(\log V)\) 了。

那么也就是说只有 \(O(\log V)\)\(nxt(r)\) 会发生改变,于是我们只需要每次更新这几个 \(nxt(r)\) 即可。然后维护跳链的信息可以使用 LCT 做到 \(O(n \log n \log V)\),不过这比较蠢,因为 NOIP 之前谁写 LCT 啊,由于 \(nxt(r) - r = O(\log V)\),也就是说每次只会跳 \(O(\log V)\),于是我们可以直接用线段树维护一个区间内从前 \(O(\log V)\) 个为止开始跳,跳到区间外的第一个点是啥,然后这个东西是容易合并的,单次 pushup 是 \(O(\log V)\) 的,而我们修改连续的 \(O(\log V)\) 个值,所以只会更新 \(O(\log n + \log V)\) 个点,于是线段树维护的复杂度就是 \(O(n \log V (\log n + \log V))\)

posted @ 2023-11-06 21:53  APJifengc  阅读(289)  评论(1编辑  收藏  举报