20230817题解


终于不挂分了!(虽然 T4 结论猜错了)

T1 sequence

思路分析

\(f_i\) 表示以 \(a_i\) 为结尾的严格连续递增子序列长度,\(g_i\) 表示以 \(a_i\) 为开头的严格连续递增子序列长度,那么容易发现求的是 \(\displaystyle \max_{j<i,a_j<a_i}(f_j+g_i)\)

考虑枚举 \(i\),则我们要找到满足 \(j<i\)\(a_j<a_i\)\(j\) 中最大的 \(f_j\)。将问题转化到值域上的 RMQ,想象一个数轴,将 \(f_j\) 插入到数轴上 \(a_j\) 对应的位置,则要求的就是数轴上 \([1,a_i-1]\) 的最大值。

由于值域有 \(10^9\),不好处理,所以先离散化。求的是前缀最大值,最方便的做法是用树状数组维护,则 \(O(n \log n)\) 解决此题。

AC 代码

T2 tower

思路分析

显然答案具有单调性,如果 \(t\) 分钟之内能消灭,大于 \(t\) 分钟必然能消灭。

考虑二分转化为判定。在 \(t\) 分钟的时间限制内,每个防御塔都可以打出 \(\lfloor\frac{t+t_2}{t_1+t_2}\rfloor\) 颗导弹。我们把这个数记为 \(p\),则总共有 \(np\) 颗导弹。

观察一下就会发现,一个导弹消灭一个敌人,这是一个匹配问题,而且敌人内部和导弹内部不会匹配,想到建图跑二分图最大匹配。

对于每一颗导弹和每个敌人都建一个点。每个导弹的发射时间都可以计算出来,记作 \(st_i\),则将这颗导弹在剩下的 \(t-st_i\) 分钟之内能够到达的所有敌人都和这颗导弹连边,最后跑匈牙利就可以完成判定。

AC 代码

T3 photo

思路分析

可以看出符合 \(h_i < h_{i+1} + 2\) 的排列有一个特点:一定是将一个顺序序列分成多个部分,并将每个部分都逆转。比如 \([1,2,3,4,5]\) 的 1 到 3 和 4 到 5分别反转,就是 \([3,2,1,5,4]\)

注意:接下来所有的下标表示的都是值域,并不是序列的坐标,而是序列中的值!!!

如果我们能求出将原序列的 \([l,r]\) 部分交换成全部反转所需的步骤(记作 \(g_{l,r}\)),就可以用 dp 解决此题。定义 \(f_i\) 表示只考虑 \([1,i]\)值域区间所需的最小步骤,那么可以通过枚举最后一段连续下降序列的长度来转移,即:\(f_i\leftarrow\min_{j=1}^{i - 1}{(f_{j}+g_{j+1,i})}\)

剩下的问题就是考虑怎么快速求 \(g\)。在目标序列中,\([l,r]\) 如果是一段连续下降区间,那么 \([l,r]\) 内部会产生全部 \(\frac{(r - l + 1) \times (r - l)}{2}\) 个逆序对,但是 \([l,r]\)\([1,l-1],[r+1,n]\) 之间不会产生任何逆序对。我们可以枚举出原序列的 \([l,r]\) 内部还差多少个逆序对没产生(有多少个“顺序对”),以及 \([l,r]\) 与外部产生了几个多余的逆序对,则 \(g_{l,r}\) 就是内部“顺序对”与外部逆序对之和。

而逆序对和顺序对本身是很好统计的。以逆序对为例:用 \(b_{i,j}\) 表示在原序列中 \(i\)\(j\) 两个数是否产生了逆序对,那么对 \(b\) 做二维前缀和得到 \(s\)\(s_{i,j}\) 就表示第一个数小于等于 \(i\),第二个数小于等于 \(j\) 的逆序对个数。逆序对对于 \(g_{l,r}\) 的贡献(即 \([l,r]\) 与外部的逆序对)就是 \(s_{r,l-1}-s_{l-1,l-1}\)

AC 代码

T4 toilet

思路分析

为了 \(n\) 分钟之内结束,两个厕所一刻都不能停。由于男生不能进女厕,所以一个男生必须要和一个女生一起才能上厕所(奇怪啊)。如果把男生视为 \(1\),女生视为 \(-1\),那么对于任意位置,后缀和必须要小于等于 \(1\) 才能保证成功。(后缀和为 \(1\) 时多出来的那个男生可以跟着他之前的女生走)。

如果出现了后缀和大于 \(1\) 怎么办呢?就需要把一些男生放到前面去。如果累计的男生个数有 \(x\) 个,则至少要放 \(x-1\) 个到女生前面,则答案应该对 \(x-1\)\(\max\)

这样的话,考虑从后往前扫描字符串,用一个变量来存储后缀和,当后缀和大于 \(1\) 时,更新一下答案。

然后考虑怎么处理重复字符串。容易想到,重复的字符串对于后缀和的影响是相同的,并且无论影响是正是负,对答案有影响的只有可能是第一个串和所有串连在一起。所以维护一个字符串产生的后缀和变化量 \(delta\) 以及变化过程中的最大变化量 \(maxdelta\),如果一共重复 \(t\) 次,并且在这个字符串之前的后缀和是 \(cnt\),那么在这些重复的字符串中,最大后缀和是 \(\max(cnt+maxdelta, cnt+maxdelta+delta\times(t-1))\),而对总后缀和的影响是 \(cnt \leftarrow cnt + delta\times t\)

最后看一下无解:如果总后缀和最终大于 \(0\)\(1\) 也不行,如果是 \(1\) 第一个男生无法上厕所),说明男生过多了,则输出 \(-1\)。否则输出过程中的最大后缀和减一。

AC 代码