代码源挑战赛 Round 79 题解 - 代码源竞赛平台

T1

100%

直接计算 x=10a+bx=10a+b、y=10b+ay=10b+a,判断 [k∣x][k\mid x] 与 [k∣y][k\mid y] 是否恰有一个为真,是则输出 Yes,否则输出 No。

时间复杂度 O(1)O(1),空间复杂度 O(1)O(1)。

T2

100%

n≤300n\le300,枚举所有 i<ji<j,共 O(n2)O(n^2) 对,计算 s=ai+ajs=a_i+a_j,以 (∣s−w∣, s)(|s-w|,\ s) 为关键字取字典序最小的一对,输出其 ss。只要求编号不同,重量相同的两个砝码可以同时选。

时间复杂度 O(n2)O(n^2),空间复杂度 O(1)O(1)。

T3

100%

不同颜色互不影响,且每种颜色至多选一张。由于 wi≥1w_i\ge1,只要某种颜色出现过,选其中权值最大的一张一定最优,这样总和最大,也自然满足"至少选一张"。

开数组 mxcmx_c 记录每种颜色的最大权值,答案为 ∑cmxc\sum_c mx_c。颜色编号不超过 nn,可直接用数组。

时间复杂度 O(n)O(n),空间复杂度 O(n)O(n)。

T4

100%

x↦⌊x/d⌋x\mapsto\lfloor x/d\rfloor 单调不降,所以把 aa 升序排序后 ci=⌊ai/d⌋c_i=\lfloor a_i/d\rfloor 也是升序。cc 与 bb 的多重集相同,当且仅当两者排序后逐位相等。因此把 aa、bb 分别升序排序,dd 合法当且仅当对每个 ii:

$$\left\lfloor\frac{a_i}{d}\right\rfloor=b_i\iff b_id\le a_i<(b_i+1)d .$$
  • ai<(bi+1)d  ⟺  d>⌊ai/(bi+1)⌋a_i<(b_i+1)d\iff d>\lfloor a_i/(b_i+1)\rfloor,即 d≥⌊ai/(bi+1)⌋+1d\ge\lfloor a_i/(b_i+1)\rfloor+1;
  • bid≤aib_id\le a_i:当 bi>0b_i>0 时等价于 d≤⌊ai/bi⌋d\le\lfloor a_i/b_i\rfloor,当 bi=0b_i=0 时恒成立。

所以每个 ii 给出 dd 的一个区间,合法的 dd 就是这些区间与 [1,M][1,M] 的交集:

$$lo=\max\Bigl(1,\ \max_i\bigl(\lfloor a_i/(b_i+1)\rfloor+1\bigr)\Bigr),\quad hi=\min\Bigl(M,\ \min_{b_i>0}\lfloor a_i/b_i\rfloor\Bigr),$$

答案为 max⁡(0, hi−lo+1)\max(0,\ hi-lo+1)。

时间复杂度 O(nlog⁡n)O(n\log n)。

T5

100%

设当前翻转标记为 ff(初始 00),删除原串中的字符 SxS_x,它的当前真实值为 Sx⊕fS_x\oplus f。若真实值为 11,则标记翻转,所以新标记 f′=f⊕(Sx⊕f)=Sxf'=f\oplus(S_x\oplus f)=S_x。也就是说,一次操作后,翻转标记恰好等于刚被删除字符的原始值。

剩余字符串全为 00,等价于其中每个原始字符都等于当前标记 ff。分情况讨论:

  • 不操作:需要原串全为 00,答案 00。
  • 剩余为空:总是可行,代价 nn。
  • 操作过且剩余非空:设剩余部分是原串区间 [l,r][l,r],则其中字符必须全为同一个值 vv,且最后一次被删除的字符值也为 vv。最后一次删除的字符一定紧邻剩余区间,即 Sl−1S_{l-1} 或 Sr+1S_{r+1}。所以 [l,r][l,r] 是某个极长同值连续段的真子段(它被一个同值字符紧邻)。

对长度为 LL 的极长连续段,最优是保留其中 L−1L-1 个字符:先把其余字符全部删掉,最后删去段内的一个同值端点字符,此时标记恰为 vv,操作数为 n−(L−1)n-(L-1)。L=1L=1 时退化为剩余为空,代价 nn,公式依然成立。

设 mm 为最长连续同值段的长度(00 段与 11 段都算),则

$$ans=\begin{cases}0,&S\text{ 全为 }0,\\ n-m+1,&\text{其他情况}.\end{cases}$$

时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。

T6

100%

不难发现合法区间的子区间一定合法。

设 bad(R)bad(R) 为所有右端点 ≤R\le R 的"x,y,x,yx,y,x,y 模式"中,第一个位置 ii 的最大值(没有模式时为 00)。以 RR 为右端点的合法区间恰为左端点 L>bad(R)L>bad(R),共 R−bad(R)R-bad(R) 个,所以答案为 ∑R(R−bad(R))\sum_R(R-bad(R))。而

bad(R)=max⁡(bad(R−1), g(R)),bad(R)=\max\bigl(bad(R-1),\ g(R)\bigr),

其中 g(l)g(l) 为最后一个位置恰为 ll 的模式中第一个位置 ii 的最大值(不存在则为 00)。

求 g(l)g(l): 设 y=aly=a_l,pp 为 yy 在 ll 之前最近的出现位置(不存在则 g(l)=0g(l)=0)。考虑模式 (i,j,k,l)(i,j,k,l),其中 ai=ak=x≠ya_i=a_k=x\ne y,aj=ya_j=y,i<j<k<li<j<k<l:

  • 若 k<pk<p,则 (i,j,k,p)(i,j,k,p) 也是模式,它的贡献已包含在 bad(p)≤bad(l−1)bad(p)\le bad(l-1) 中,无需再考虑;
  • 若 k>pk>p,则 j≤p<kj\le p<k,把 jj 换成 pp 得到模式 (i,p,k,l)(i,p,k,l),ii 不变。

所以只需考虑 j=pj=p,即 i<p<k<li<p<k<l 且 ai=ak≠ya_i=a_k\ne y。ii 取尽量大,不妨设 ii 是其颜色在 pp 之前的最后一次出现(若不是,则更靠后的出现位置也满足条件且更大)。记 nx(i)nx(i) 为 aia_i 的下一次出现位置,条件化为

g(l)=max⁡{ i : i<p<nx(i)<l }.g(l)=\max\{\,i\ :\ i<p<nx(i)<l\,\}.

其中 nx(i)>pnx(i)>p 说明 ii 是其颜色在 pp 之前的最后一次出现,也自然保证 ai≠ya_i\ne y(否则 nx(i)≤pnx(i)\le p);p<nx(i)<lp<nx(i)<l 说明 aia_i 在 (p,l)(p,l) 内再次出现。

具体实现如下:

用线段树按下标 ii 存 nx(i)nx(i)(未加入时为 00),维护区间最大值。从左到右处理 ll:先把 nx(i)=l−1nx(i)=l-1 的那个 ii(即 l−1l-1 的上一次出现位置,若存在)加入,保证所有 nx(i)<lnx(i)<l 的项都已加入;然后在下标范围 [1,p−1][1,p-1] 中,用线段树二分找到最大的、值 >p>p 的下标,它就是 g(l)g(l)(找不到则 g(l)=0g(l)=0)。更新 bad(l)bad(l) 并累加 l−bad(l)l-bad(l)。

时间复杂度 O(nlog⁡n)O(n\log n)。