2024.6 做题记录
2024.6 做题记录
[JSOI2009] 球队收益 / 球队预算
考虑到要求最小总支出,想到最小费用流。
首先容易发现,每场比赛都只有两种可能,即甲输乙赢或甲赢乙输。但是这样我们在跑费用流的时候显然需要考虑对于两个因素同时的影响,显然这样不好做。我们不妨假设剩下的比赛所有人都输,那么我们就只需要考虑每一场比赛赢的贡献即可。
现在我们先考虑建图。首先有 \((s,ss,m,0)\) 表示 \(m\) 场比赛的限制,然后应该有 \((s_i,i+n,1,0),(t_i,i+n,1,0),(i+n,t,1,0)\),也就是从比赛双方球队向比赛连边,流量是 \(1\)。然后再从比赛向汇点连边,流量为 \(1\),这样就可以限制每场比赛的胜利者只有一个。
现在的问题就在于如何计算赢一场比赛的贡献,也就是 \(ss\) 和球队 \(i\) 之间怎样连边。
考虑我们原先假设的是所有球队都输,于是如果一支球队在 \(m\) 场比赛中打了 \(p_i\) 场,原先的费用就应该是 \(c_i{a_i}^2+d_i(b_i+p_i)^2\)。现在考虑如果这支球队赢了 \(q_i\) 场,那么现在的费用就是 \(c_i(a_i+q_i)+d_i(b_i+p_i-q_i)^2\)。现在对两者做差,就可以求出赢 \(q_i\) 场对答案的贡献为:
如果将 \(q_i\) 看作流量,那么发现式子中出现了平方费用流,考虑拆边处理。设上式中 \(q_i\) 系数为 \(A\),\({q_i}^2\) 系数为 \(B\),则我们从 \(ss\) 向 \(i\) 连边 \((1,A+B),(1,A+3B),(1,A+5B),\cdots,(1,A+(2p_i-1)B)\)。其实相当于将原来 \(q_i\) 的流量拆成 \(1\) 的流量,然后累加起来达到平方费用的效果。
最后我们跑最小费用最大流,最小费用再加上假设所有队都输的费用就是最后答案。
[CQOI2017] 老C的方块
首先它让我们求删去的最小费用,可以想到最小割。
观察题目中给出的四种不能存在的形状,我们发现他们有一个共同点:特殊边两边都有方块且两边的方块都还有一个相邻的方块。同时我们再观察题目,发现在特殊边两边的方块与和特殊边两边的方块相邻的方块是交替出现的。
那么既然要描述限制,自然想到黑白染色。我们可以将在特殊边两边的方块染成黑色,其余方块染成白色。但是这时候我们发现,如果想直接连边,同种颜色内的方块仍然会互相影响(也就是特殊边两边的方块仍没有规定顺序)。于是我们就想到再对每一类方块进行染色,将在特殊边左边和在特殊边右边的方块分成两种颜色,那么自然的,与特殊边左边的方块相邻的其他方块和与特殊边右边的方块相邻的其他方块也要分成两种颜色,同时我们还要满足颜色之间的连边顺序不能改变。
根据这样的思路,我们就可以染出下面的图(以题目中 \(8\times 8\) 方格为例,| 表示特殊边):
3 4 2|1 3 4 2|1
1|2 4 3 1|2 4 3
3 4 2|1 3 4 2|1
1|2 4 3 1|2 4 3
3 4 2|1 3 4 2|1
1|2 4 3 1|2 4 3
3 4 2|1 3 4 2|1
1|2 4 3 1|2 4 3
此时我们发现,对于任意一种不能存在的形状,一定可以走出一条 \(3\to 1\to 2\to 4\) 的路径。所以我们按照这样的顺序在点之间连边,只要能将所有这样的路径断开就表明不会存在这些形状。显然断开就是求最小割,跑出最小割就是最后的答案。
当然,由于题目中给的是点权,所以自然还要用传统功夫拆点转化为边权。做到这里这个技巧应当是显然的了,不再赘述。
[SCOI2012] 喵星球上的点名
这道题牛就牛在它几乎没有任何一步是好想的。
首先我们看到姓和名是分开的,自然想到在中间加上一个字符。然后问题其实就是用多个模式串去匹配多个文本串,显然可以 AC 自动机,但是我们要用后缀数组。
考虑将所有文本串和模式串全部拼起来变成一个大串,两个串之间加上一个字符。现在我们跑出后缀数组,求出 \(sa\) 和 \(height\)。现在在 \(sa\) 中,有一些值是大串中模式串的开头;如果文本串要与之匹配,则两者的 LCP 必定是该文本串的长度。由于在 \(sa\) 中的 LCP 就是 \(height\) 上的 RMQ,所以我们可以得到这样一个结论:越往两边走最小值一定不会更大,也就是越往两边走 LCP 一定不会更长。
于是我们想到可以求出对于一个模式串的开头,它向左向右最远能和哪些后缀匹配上。根据上面的结论,在这个开头左(右)边的点与这个点的 LCP 满足单调性,因此可以二分求解(RMQ 直接利用 ST 表即可)。
现在对于模式串的开头,我们可以得到一个区间 \([l,r]\),表示在 \(sa\) 上这个区间所有的数对应的后缀都可以和这个模式串匹配。那么我们记录下 \(sa\) 上每个数对应的文本串,第一问就可以转化为求出在 \(sa\) 的区间 \([l,r]\) 中,不同文本串编号的数量。显然可以使用莫队求解。
现在考虑第二问,为了保证莫队的根号复杂度,这一问的求解必须和莫队的复杂度一致。但是光靠记录文本串出现此时似乎并不能解决这个问题。此时我们考虑差分思想:当这个文本串第一次出现时,给它的答案加上剩余模式串的数量;当这个文本串不再出现时,给他的答案减去剩余模式串数量。这样我们就可以求出这个文本串究竟匹配上了多少个模式串。
[AHOI2013] 差异
首先看到题目中给了我们一个式子,但是我们看不懂这个式子,所以爆算一下:
现在后面那个东西要求 \(i<j\),考虑到最后结果要乘 \(2\),因此实际中我们不需要考虑 \((i,j)\) 的顺序,只要对于每个无序的 \((i,j)\) 都计算一次即可。
现在我们来看怎样求 LCP,显然考虑后缀数组。在求出 \(height\) 数组后,我们的问题在于,如何求出后面那个式子。显然暴力 RMQ 是 \(O(n^2)\) 的。考虑固定一个 \(ht[i]\),找出区间最小值为 \(ht[i]\) 的所有区间,显然这些区间的贡献就是 \(ht[i]\)。
既然如此,我们就找出在 \(i\) 左边第一个 \(ht[l]<ht[i]\) 的点,找出 \(i\) 右边第一个 \(ht[r]<ht[i]\) 的点,这样理论上左端点在 \((l,i]\)、右端点在 \([i,r)\) 的区间最小值都是 \(ht[i]\)。但是这样操作下来可能会有重复,所以我们需要将上面的两个小于条件中的一个改为小于等于,这样我们就不会再算重了。
至于如何求解,显然这是单调栈的裸题。最后区间最小值为 \(ht[i]\) 的区间个数就是 \((i-l)(r-i)\),贡献自然是 \((i-l)(r-i)\times ht[i]\)。
最后算出所有贡献之和,乘上 \(2\) 之后用 \(\dfrac{n(n-1)(n+1)}{2}\) 减去就是答案。
[bzoj3230] 相似子串
首先题目中说的 \(a^2+b^2\) 最大值,其实就是分别让 \(a,b\) 最大,也就是求出两个子串之间的最长公共前缀和最长公共后缀。
那么现在我们一步步解决这个问题。首先就是题目中给出的是子串的排名,我们需要将其对应到后缀的前缀上。由于给出的是排名,那么我们只需要知道每个后缀的排名,然后二分查找出属于哪个后缀即可。
第二个问题就是如何求出后缀的排名。根据不同子串数量的思路,我们每个后缀所产生的新的子串是该后缀长度减去 \(height[i]\)。而这些子串的排名又都在这个后缀之前,于是该后缀的排名就等于上一个后缀的排名加上所有子串的个数。
现在我们求出了子串的排名,顺便就可以求出子串开头的位置和长度。接下来先考虑求出两个子串的 LCP,我们求出两个子串对应后缀的 LCP,再与两个子串的长度取 \(\min\) 即可。
现在考虑求公共后缀。我们考虑将原字符串反转一次后求后缀数组。由于上面我们已经求出了子串开头的位置,所以自然能求出反转后开头的位置,也就是求出了反转后对应的后缀。将这两个后缀求出 LCP 与子串长取 \(\min\),得到的就是子串的最长公共后缀。
将两者带入 \(a^2+b^2\) 计算即可。
[NOI2015] 品酒大会
首先我们先跑出后缀数组,接下来考虑求出所有 \(r\) 相似串的信息。暴力的思路是在 \(sa\) 上枚举两个后缀,然后利用 RMQ 求出最长的 \(r\),更新对应的答案。由于题目中说了 \(r\) 相似串也是 \(1,2,\cdots r-1\) 相似的,所以我们最后的答案还需要倒序累加一遍才行。
上面的做法显然是 \(O(n^2)\) 的,考虑优化。实际上我们就是在求出所有后缀之间的 LCP,然后维护一些信息。求所有后缀之间的 LCP,这容易让我们想到 [AHOI2013] 差异 中的处理方式。实际上,我们的确就是这么做。
对于 \(i\),求出左边第一个满足 \(ht[l]<ht[i]\) 的 \(l\),以及右边第一个满足 \(ht[r]\le ht[i]\) 的 \(r\)。这样左端点在 \([l,i)\)、右端点在 \([i,r)\) 的区间的最小值绝对是 \(ht[i]\)。也就是说这些区间绝对都是 \(ht[i]\) 相似串,那我们就给 \(ht[i]\) 的答案一加上 \((i-l)(r-i)\) 即可。
接下来既然知道这些区间都是 \(ht[i]\) 相似的,那我们还要求出调兑后的最大值。考虑要求的两个数一定也是分别在 \([l,i),[i,r)\) 两个区间中的,所以我们用 ST 表维护出 \(sa\) 上 \(a\) 的极值(注意还需要维护最小值,因为可能有负负得正),然后组合起来相乘得到这些区间中的最大值,将答案更新即可。
最后从后往前再更新一次,求出最后的结果即可。
[ZJOI2009] 对称的正方形
我们发现这道题可以理解为求一个回文的正方形,于是我们继续沿用马拉车的思想。考虑在矩阵中插入 0,使得矩阵变成 \((2n+1)\times (2m+1)\) 的。此时我们所有的回文正方形都是奇数长度的,也就是有唯一中心的。我们考虑枚举这个中心,复杂度就是 \(O(nm)\) 的。这意味着我们剩下的操作必须在 \(O(\log n)\) 以内完成。
考虑二分以当前格子为中心的回文正方形边长。现在问题就是如何判断。我们知道这个正方形要满足上下对称和左右对称,也就是说每一行和每一列都应该是回文串。假如当前格子是 \((x,y)\),边长为 \(a\),那么为了满足上下对称,在 \(x\) 这一行上在当前正方形之内的格子,向上下延伸出的回文串长度至少需要是 \(a\)。在 \(y\) 那一列上的格子同理。
显然我们用 Manacher 可以求出每个格子向上下左右能延伸的最长回文串,于是问题又在于判断所有格子延伸长度是否达到 \(a\)。考虑这样的思路:如果最小的延伸长度都达到了 \(a\),显然它们全部能达到 \(a\);否则显然不行。那么我们就会想到利用 ST 表维护每一行每一列上格子 \(d\) 的最小值,在二分时判断即可。
这样做复杂度就只有二分的 \(O(\log n)\),符合我们的预期。最后我们得到了每一个格子向外延伸的正方形边长,将添加的 0 减去即可。
[CERC2014] Virus synthesis
首先容易发现的性质是:最后的字符串一定是由偶数长度的回文串在加上两边的零散字符拼接而成。这个性质是显然的,因为奇数长度的回文串根本不可能被反转得到。也就是说,我们现在只需要考虑构造偶数长度回文串的步数,剩下所有字符串用的步数都是字符串长度。
现在考虑怎样构造偶数长度回文串。我假设 S 是一个回文串,a 和 b 分别是一段不回文的字符(a 非空)。那么这个偶数长度回文串只有两种表达:aSbbSa 和 SbbS。
显然构造出后一种的步数就是构造出 S 的步数加上 b 含有的字符数,而由于 S 在结尾处,我们就可以使用 trans 数组找出这个 S 然后转移。设 \(dp(i)\) 表示构造出 PAM 上第 \(i\) 个节点代表回文串的步数,那么对于这种情况,转移为:
现在考虑前面的情况,由于 S 不在中间,因此不能直接走 trans 转移。但是我们发现,从 SbbS 变为 aSbbSa 其实走的是最原始的回文树上的边。因此对于这种情况的转移为:
对于剩下的所有字符串,直接将 \(dp(i)\) 赋为 \(len(i)\) 即可。
那么所有情况就讨论完了,现在考虑求答案。显然对于一个偶数长度回文串 \(i\),答案为 \(n-len(i)+dp(i)\)。取最小值即可。
但是我们发现这个 dp 转移似乎是在 DAG 上的,好像要用拓扑排序。实际上不然,由于 PAM 是一个一个字符添加的,所以保证了后加的编号都大于前面加的,也就是说 \(trans_i\) 和 \(fa_i\) 一定都小于 \(i\)。于是我们就不需要拓扑了,直接枚举递推即可。

浙公网安备 33010602011771号