PA2021 部分题解

PA 2021 部分题解

「PA 2021」Oranżada

无解条件显然,若 ai 的种类数小于 k,那么输出 1

否则贪心的取前 k 个不同的 ai 就好了。

具体细节看代码。

Code


「PA 2021」Od deski do deski

先考虑对于一个固定的序列,判断其是否合法。

gi 表示 [1,i] 是否能被删除,那么如果存在一个 j[1,i1] 满足 gj1=trueai=aj

也就是说,若一个位置 ai 满足前缀 i1 是合法的,那么再往后出现 ai 的位置代表的前缀都是合法的。我们称这样的值为特殊值

于是可以从左到右扫描序列,记录当前前缀的特殊值集合 S,以及当前前缀是否合法。加入一个数时,若前缀合法,则加入的值会成为特殊值。可以通过集合 S 直接判断新前缀是否合法。

接着考虑计数,可以发现计数时不关心特殊值集合 S 具体是什么,只关心它的大小。因为通过上面的方法可知加入的数只关心其是否是特殊值。

fi,j,0/1 表示长度为 i,特殊值集合大小为 j,不合法/合法的序列个数。

转移需要分类讨论一下,共四种:

  • 当前前缀合法,继续填特殊值依旧合法,并且特殊值数量不会增多。fi,j,1×jfi+1,j,1
  • 当前前缀合法,但是填不是特殊值的值,那么将变的不合法且特殊值数量增加一。fi,j,1×(mj)fi+1,j+1,0
  • 当前前缀不合法,填一个特殊值,那么将变的合法且特殊值数量不会增多。fi,j,0×jfi+1,j,1
  • 当前前缀不合法,填一个不是特殊值的值,那么依旧不合法且特殊值数量不会增多。fi,j,0×(mj)fi+1,j,0

最终答案为 ifn,i,1

时间复杂度 O(n2)

具体细节看代码。

Code


「PA 2021」Zbalansowane słowa

首先对于原题,字符集大小只有 3

那么就有一种 O(2Σn) 的做法。

枚举字符集,然后构造和为 0。具体的,对于当前枚举的字符集,给前面的几个字母随一个权值,并给最后一个字母的权值设为前面几个字母权值和的相反数。

手写哈希即可做到 O(2Σn),但是我懒用了 map 所以多一只 log,不过没有关系,足以通过原题了。

具体细节看代码。

Code

但是呢,字符集是可以开到 26 的!!!

定义一个字符串的状态为它的字符集,即 aa 的状态为 1000abd 的状态为 11010000

不难发现每个点作为左端点只有 26 种状态,作为右端点也只有 26 种状态。

设当前状态为 Slen=|S|

给每个字母随一个 ull 范围的权值。

设当前状态的每个字母的权值和为 sum,字符串的权值前缀和为 si

那么一个区间合法说明 srsl1=rl+1len×sum

移项得 sl1l1len×sum=srrlen×sum,可以把条件再改一下,设 X 是一个很大的数,则 sum×X+sl1l1len×sum=sum×X+srrlen×sum

prei 表示 i 前面字符集按最后一次出现的位置排序的顺序,sufi 表示 i 后面字符集按第一次出现的位置排序的顺序。

拿字符串 abbcda 举例。

pre4={c,b,a},pre6={a,d,c,b},suf1={a,b,c,d},suf3={b,c,d,a}

fi,j 表示以 i 为右端点,状态大小为 j 的值,gi,j 是以 i 为左端点,状态大小为 j 的值。f 的计算需要用到 preg 的计算需要用到 suf

那么最终就是从后往前枚举,插入右端点的值,查询左端点的值。

具体细节看代码。

Code


「PA 2021」Desant 2

首先有个很显然的暴力 DP,记 fi 表示前 i 个数的答案,sumi 表示 a 的前缀和。

那么 fi=max(fi1,fik+sumisumik)

这样复杂度是 O(nQ) 的。

但是可以借鉴一下 这题 的思路。

可以把 DP 的过程看成在图上遍历,当前是否选连出去两条边,k 个点排成一列,可以连成类似这样一张图:

其中横向边的权值是区间和,纵向边的权值是 0

特殊边23,56,89 这种。

问题变为在图上查询最长路。

考虑分治,若行数不超过列数,考虑跨越中间列的询问一定经过中间列的点,对每个中间列的点求一遍所有点到其和其到所有点的最长路,即可处理这些询问,然后分治下去,复杂度 O(nn)

否则,考虑跨越中间行的询问一定经过中间行的点,或者通过至少一条特殊边,对这些点边做一遍上一部分一样的过程即可,然后分治下去,复杂度 O(nn)

细节有点多,可以看代码好好领悟。

Code


「PA 2021」Koszulki

简单贪心。

Code


「PA 2021」Pandemia

如果不考虑头部和尾部,那么我们设中间的连续为 0 段的长度分别为 a1,a2,,ak。那么贪心的,我们直接将 a 按照降序排列,然后模拟。

那么如果考虑头部和尾部呢?

继续贪心,显然保护头部或尾部只需一个时间,那么我们在开头就保护。

上述贪心都是基于直觉,也不难证明是正确的(其实我不会证)。

具体细节看代码(自认为写的很丑)。

Code


「PA 2021」Poborcy podatkowi

我们考虑设 fu,i 表示的是以 u 为根的子树,u 留给父亲的链长为 i 的已选边的边权之和最大值。

难点在于转移,考虑以 fu,0 为例,列举我们需要的条件:

  • 接到这个点上的长度为 1,3 的链的数量相同。
  • 长度为 2 的链的数量为偶数。

可以设 gi,j 表示选了长度为 1 的链的个数减去长度为 3 的个数为 i,长度为 2 的链的数量的奇偶性为 j 时所选边权的最大和。但是发现第一维是 O(n) 的,总复杂度为 O(n2)

但是有个非常震撼的东西,将儿子序列随机打乱,就可以把第一维控制在 O(n)

谁管证明啊(

具体细节看代码。

Code


「PA 2021」Zakłócenia

小清新构造,直觉上尽可能平均分是最优的,也不难证明是正确的。

Code


「PA 2021」Sumy

简单题,显然答案具有单调性,二分即可。

Code


「PA 2021」Mopadulo

sumi=(ij=1ai)mod109+7,那么 fi 能被 fj,j<i 转移到需要满足以下任意一个条件:

  • sumj>sumisumjsumi 奇偶性不同。
  • sumjsumisumjsumi 奇偶性相同。

维护两个树状数组即可。

具体细节看代码。

Code


「PA 2021」Ranking sklepów internetowych

不难发现权值的最大值是 2n+1,计数的话就枚举区间长度,维护一下区间端点的合法区间就可以了。

具体细节看代码。

Code


「PA 2021」Butelki

比较震撼,直接 BFS 即可,因为状态数是线性的。

简单说明一下,考虑一次操作之后,必定有一个瓶子的状态为空或者满了。那么共 6 种情况,对于每种情况,剩下两种瓶子的总量是固定的。所以状态数是线性的。

具体细节看代码。

Code


「PA 2021」Drzewo czerwono-czarne

更加震撼的一题。

先判掉一些平凡的 Case:

  • c=c,输出 Yes
  • c 中只有一种颜色,输出 No
  • c 中,任意 (u,v)E 都有 cucv,输出 No

前两个 Case 显然。第三个 Case 是由于我们最后一次操作的时候肯定会造出来两个相同颜色的点, 所以不可能没有这样的点对。

然后是最震撼的东西,如果存在一个度数 3 的点,输出 Yes。

因为我太菜,所以我暂时还没有完全看懂证明,所以这里贴一个 Qingyu 大佬的证明。(也可以看官方题解,不过看中文总比看波兰语翻译过来的要好吧。。)

否则原来的树就是一条链啦

  • 如果序列开头的元素不一样, 那么我们只能把头给删掉, 因为我们只能merge 两个连续段, 不能 swapsplit
  • 如果删掉以后,c 的连续段数目 < c 的连续段数目就是 No,否则是 Yes。
  • 证明仍然是类似的调整。注意到我们总是有一段的长度 2,所以我们一定可以通过伸缩一段让前面一段自由。

时间复杂度为 O(n)

具体细节看代码。

Code

posted @   Kobe303  阅读(1043)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示