√:vp 时独立做出。
√:vp 后独立做出。
√:经过提示后做出。
−:未做出。
×:尝试提交过,未做出。
A
√,*900。
《开幕雷击》,vp 的时候被这糖题卡了。
考虑到同一种字母构成的子序列带来的贡献无论如何都无法去除,贪心地尽量让同一种字母放在一块即可;同时每种字母的数量应尽量平均,所以直接先将每种字符添加 ⌊5n⌋ 个,再将剩余的 nmod5 个字母添加进来即可。
B1
√,*1000。
简单版本,n=2。设 min(b0,b1)=l,max(b0,b1)=r。
分类讨论:
- 当 a<l 时,学生会被在 l 处的老师抓到,此时最优策略一直往左跑到 1,答案为 l−1。
- 当 a>r 时同理,答案为 n−r。
- 当 l≤a≤r 时,学生的策略是向中间跑。设 m=⌊2l+r⌋,答案为 min(m−l,r−m)。
B2
√,*1200。
策略跟原来一样,排序后加个二分每次询问找到找到 l,r 的值即可。
C
√,*1800。
发现选字符串的过程对之前的选择是无后效性的,考虑 dp。设 fi,j 为当前选择到第 i 个字符串,前面的选择为当前贡献了 narek
中的前 j 个字符。
不选第 i 个字符串的转移是 fi−1,j→fi,j,若选中第 i 个字符串,假设 j=2,前面贡献了 na
两个字符,则能带来贡献的子序列一定形如 reknareknarek...nar
,扫一遍字符串,统计出能匹配上的子序列长度 x 和末尾剩下的字符数量 w,则有转移 fi,j+x−(m−x)→fi,j+wmod5。
最终答案则为 maxi=04{fn,i−i},注意 −i 是因为最后一次未匹配到的字符是不计入得分的。
D
−,*2400。
困难啊,明明刚学过序列分治还是一点思路没有。
先用 st 表预处理 gcd,然后进行序列分治,函数 solve(l,r) 返回的是对于所有被区间 [l,r] 包含的操作中能达到的最大答案与达成该答案的方案数。
操作一段区间相当于留下一段前缀 gcd 和一段后缀,由于 gcd 的性质,不同的前 / 后缀 gcd 个数最多只有 log 个。
于是在序列分治的过程中,我们对左右两边分别统计,枚举(如图所示的)红 / 蓝色段的分界点,用一个二元组 (x,y) 代表“在左 / 右侧,红色段的 gcd 为 x,蓝色段的 gcd 为 y”。用两个 map 记录左 / 右侧每个 (x,y) 出现的次数,由于前面提到的性质,这样的二元组总共最多有 log2 个。
处理完之后,我们二重循环枚举左右两个 map 中的二元组 (x0,y0) 和 (x1,y1),把它们拼在一起,最后结果即为 gcd(x0,x1)+gcd(y0,y1),正常更新答案即可。
这样做的时间复杂度实际上是 nlog2n 而非 log3,由两部分组成:更新 map 的复杂度就是正常序列分治的 nlogn 乘以查询 gcd 的 logn,而枚举二元组的部分由于序列一共只会被划分成 O(n) 个区间,最多枚举 log2 种两个二元组的组合,复杂度同样是 nlog2n。
E1
√,*2100。
vp 的时候没时间写了,感觉挺简单的。
简单版的数据范围比较小,可以考虑直接暴力 dp,设 fx,i,j 代表当前要获取的元素是 ai 且呆在 (i,j) 处时是必胜还是必败。首先若 bi,j=ax 一定必败。否则,由 SG 函数可知,当且仅当当前状态能走到的后继状态全都是必败状态,这个状态才是必胜状态。于是按游戏规则可得 fx,i,j=[∑i<i′≤n,j<j′≤mfx+1,i′,j′=0]。直接转移是 O(n2m2l) 的,每次求一遍二维前缀和优化一下,实现 O(1) 转移即可。初始状态为 fl,i,j=[bi,j=ai],时间复杂度 O(nml)。