原神,启动!|

yshpdyt

园龄:1年1个月粉丝:6关注:4

AGC037 题解

这篇写的跨度有点太长了不记得当时的想法

[AGC037A] Dividing a String

题意

给定一个字符串 \(S\),请你找出一个最大的 \(k\),使得将这个字符串划分成 \(k\) 段后能够保证相邻的两段不相同。

\(1\le |S| \le 2\times 10^5\),且保证 \(S\) 串内均为小写字母。

idea

简单 \(dp\),考虑段长 \(1\)\(2\) 交替分割一定满足题意,设 \(f_{i,0/1}\) 表示当前考虑到第 \(i\) 位,第 \(i\) 位属于的段长是 \(1/2\),转移时符合条件即可。

[AGC037B] RGB Balls

题意

给出一个只包含 \(R,G,B\) 的字符串,保证它们三种字符出现的次数都为\(n\),现在你要将这 \(3n\) 个字符分给 \(n\) 个人,使得每个人都拿到了三种字符,假设某人的三个字符在序列中的位置为 \(p_1,p_2,p_3\),其中 \(p_1≤p_2≤p_3\),那么这个人的贡献为 \(p_3-p_1\),问使得总贡献最小的方案数有多少,答案对\(998244353\)取模。

\(1 \leq n \leq 10^5\)

idea

考虑先最小化答案,感性理解,同一人的所有字符离得越近越优,即对于每个前缀新加入一个字符,优先给配对了两种字符的人贡献,其次给配对了一种字符的人贡献,最后在分配给新的一人。

于是发现 \(p_3-p_1\) 的贡献,可以在独自开一组时 \(-p_1\),在填最后一个字符时\(+p_3\),贡献可以分离,例如当前位置是 \(R\),给前面任意组合 \(BG\) (或 \(GB\))贡献相同,可以利用这点统计答案。

于是记 \(r,g,b,rg,rb,gb\) 表示对应组合的个数,利用上述方法转移即可。这样会不会因为如 \(R\) 不知道贡献给单独的 \(G\) 还是单独的 \(B\) 而出问题?事实上,这样会形成 \(gb\) 所以不会出现。

这样的做法钦定了按编号顺序从小到大匹配,最终答案需要乘 \(n!\)

[AGC037C] Numbers on a Circle

题意

一个环上有 \(n\) 个正整数,一次操作可以令 \(A_i\leftarrow A_{i-1}+A_i+A_{i+1}\),求多少次操作可以使 \(A\) 变成 \(B\),无解输出 \(-1\)

\(1 \leq n \leq 2\times10^5\)

idea

加法的可能性太多,随随便便就超过限制了,考虑倒着对 \(B\) 进行减操作,由于原序列最后操作的元素会比较大,为了防止减成负数,我们应该对每个极大值点,即 \(B_i>B_{i-1}+B_{i+1}\) 这样的 \(i\) 优先操作,对于所有符合题意的 \(i\) ,不妨设一堆相邻的极大值点一个为 \(i_1\),另一个为 \(i_2\),其满足 \(|i_2-i_1|+1\ge3\),这也就是说 ,\(i_1\) 操作不会使 $i_2 $变成非极大值点,于是乎所有极大值点无关操作顺序。

考虑每次如何快速求出一个极大值点,显然的,序列的最大值一定是一个极大值点,于是可以用优先队列维护,每次取出最大值进行操作直到该位置非极大值点,或已经 \(\le A_i\),每次每个数至少减少一半,这是因为如果 \(2(B_{i-1}+B_{i+1})< B_i\),减若干次后 $ B_i'<B_{i-1}+B_{i+1}$,如果 \(2(B_{i-1}+B_{i+1})\ge B_i\),减一次后 $ 2B_i'\ge B_i$,于是复杂度为 \(O(n\log n\log V)\)

[AGC037D] Sorting a Grid

题意

一个 \(n\times m\) 的矩阵 \(A\),元素为 \(1\)\(n\times m\) 的排列。

  • \(A\) 每一行的元素任意排列得到 \(B\)
  • \(B\) 每一列的元素任意排列得到 \(C\)
  • \(C\) 每一行的元素任意排列得到 \(D\)

要求 \(D_{i,j}=(i-1)\times m+j\) , 请输出一组合法的 \(B, C\).

\(1\le n,m\le 100\)

idea

如果给 \(D\) 每行染一种颜色的话,需要满足以下条件:

  • \(C\) 中每行颜色相同。
  • \(B\) 中每列包含 \(n\) 种颜色。

于是每种颜色对所在的行建边,考虑对每列跑一边二分图匹配即可构造。

[AGC037E] Reversing and Concatenating

题意

给定长度为 \(n\) 小写字母字符串 \(s\) 和正整数 \(k\),求进行 \(k\) 次如下操作后字典序最小的 \(s\) :

  • \(s\)\(s\) 的翻转拼接得到 \(t\) , 从 \(t\) 中截取长度为 \(n\) 的子串作为新的 \(s\).

\(n\leqslant 5000,k\leqslant 10^9\)

idea

很有意思的题。

考虑 \(k=1\),最优策略不必多说复制一遍枚举找最短的即可。

\(s\) 的最小值为 \(c\),其中的最长连续段长度为 \(l\),我们的策略肯定是要使 \(l\) 尽可能被复制,但是第一次 \(l\) 可能不在末尾,这很不好操作,于是我们先强制操作一次变成长度为 \(2n\) 的字符串 \(t\),找一次操作后最适合操作的子串再进行操作。

使 \(c\)\(l\) 成为 \(t\) 的最小值和最长连续长度,我们发现一次操作使 \(l\)\(2\),于是我们最后有 \(\min(2^{k-1}l,n)\)\(c\)

对于 \(2^{k-1}l<n\) 的情况,使剩下的 \(n-2^{k-1}l\) 的字典序最小。回顾我们的操作过程,发现每次的串形如这样:\(t=\overline{xyzcccczyx}\),最后一次操作会取得是:\(s=\overline{ccccz}\) 这样的形式,其实是选择的长度为 \(l\) 的区间 \([x,x+l-1]\) 之前的一段后缀,我们只需要翻转 \(t\) 把所有长为 \(l\)\(c\) 段的最小后缀,暴力去找即可。

[AGC037F] Counting of Subarrays

题意

给定 \(l\),连续至少 \(l\) 个相同的数 \(k\) 可以合并成 \(1\)\(k+1\)

给定一个长度为 \(n\) 的序列,问该序列有多少个子区间可以通过若干次合并变成 \(1\) 个数。

idea

构式题。

考虑判断一个区间是否合法,记 \(w\) 为一个区间的最大值:

  • 区间只有一个数,该区间属于级别 \((w,l)\)
  • 区间只有 \(w\),且 \(w\) 的数量 \(\ge l\),该区间属于 \((w+1,l)\)

第一种情况答案就是 \(n\),对于第二种情况,注意到一个区间属于的级别只和最大值有关,对于 \(<w\),只有尽可能的合成,才可能会产生贡献。

于是我们初步的思想便有了,按从小到大的顺序,每次取出一段值为 \(w\) 极长连续区间进行计算,计算完毕后,如果可以合成 \(w+1\) 就塞回去,否则删掉即可。

考虑如何计算的问题,我们对序列的每个位置维护其成为左端点和右端点的方案数,对于区间 \([1,k]\),考虑左端点在 \(1\)\([1,l-1]\) 无法成为右端点,\([l,2l-1]\) 可以成为第一个右端点,依次类推即可。

但是这样还没有完,对于第 \(l\) 个右端点,这些区间会被 \(x\) 统计一次,合并后还会被 \(x+1\) 再统计一次,我们需要容斥掉这些多余的方案数。

计算完成后如何合并的区间 \(<L\) 我们就将这段区间删除,用链表维护即可。

本文作者:yshpdyt

本文链接:https://www.cnblogs.com/yshpdyt/p/18435662

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   yshpdyt  阅读(11)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起