ICPC2023深圳部分题解(A,D,E,F,G,K,L)
正题
好像还没上gym所以放不了题目链接,深圳这场的题目我觉得都很好所以写个题解。
会做的都写上来了,场上很多题是队友写的,只是有参与讨论所以知道做法的题。
A 一道好题
题目大意
长度为 \(n(1\leq n\leq 1000)\) 的序列 \(a\) ,初始全为 \(0\) ,有两个操作
- 将第 \(x\) 个数加 \(1\) 。
- 将所有值为 \(x\) 的数加 \(1\) 。
要求在 \(20000\) 次操作内变成目标序列 \(b\ (b_i\leq 1000)\) 。
解题思路
考虑分治,将所有相等的数压在一起先,然后每次让后半截先 \(+1\) 然后就可以提出后半截变成子问题了。
做完后半截再做前半截。
这样大概是 \(n\log n\) 次。
D 机器人兄弟
题目大意
给一棵以 \(n\) 为根的树,\(1\sim m\) 号点是叶子,两个人从根开始轮流向叶子走,走到叶子就结束,如果一个人所在的编号为另一个人的编号 \(+1\) (模 \(m\) 意义下),则这个人胜利。
求胜负情况。
\(1\leq \sum n\leq 5\times 10^5\)
解题思路
后手一定不会输,因为可以跟着先手走,那么我们考虑什么情况下先手会输。
我们先把每个叶子向上的链一直缩到第一个有分叉的地方,保证每个叶子的父节点处一定有分叉,那么如果叶子的深度不同,那么肯定有深度浅的叶子 \(x\) 必胜深度深的叶子 \(y\) ,那么如果后手跟着先手走到了 \(y\) 父节点的深度,那么先手直接走到 \(y\) 就打平了,如果先手走到了 \(x\) ,那么先手直接在 \(y\) 的父节点处走到另一个分叉就可以了。
所以现在所有叶子深度必须相同,然后我们考虑把这些叶子向上合并,我们考虑这些叶子的父节点们,如果 \(x\) 下面的所有叶子都被 \(y\) 下面的所有叶子控制,那么我们可以直接缩减一层,否则先手走到无法被必胜的父节点处就肯定可以打平。
那么做法就很简单了,只要不同的判断是不是所有父节点都是相互必胜的就好了,如果可以就去掉叶子层,如果不可以就直接打平。
时间复杂度:\(O(n)\)
E 二合一
题目大意
给出一个长度为 \(n\) 的序列,记 \(c(l,r,x)\) 表示区间 \([l,r]\) 中 \(x\) 的数量。
求一组 \((l,r,x,y)\) 最大的
\(1\leq \sum n\leq 5\times 10^5\)
解题思路
我们先把区间拉到 \([1,n]\) ,然后记 \(a=c(1,n,x),b=c(1,n,y)\)
然后每次你缩减区间的时候会让 \(a=a-1\) 或者 \(b=b-1\) ,然后我们记 \(a\ and\ b\) 最高位为 \(x\) ,那么 \(a\) 和 \(b\) 肯定会有一个数字先将最高位 \(x\) 减到退位,此时 \(a\ or\ b\) 的 \(x\) 位和更低位的位置都会为 \(1\) ,而前面位的位置就等于 \(a\ or\ b\) 高于 \(x\) 位的值。
所以直接取出最大的两个不同的 \(a\) 和 \(b\) 就行了。
F 见面礼
题目大意
给出一棵基环树,问有多少种方案删除环上一条边并且选定一个根,使得每个节点的儿子数都不超过 \(3\) 。
\(2\leq n\leq 10^5\)
解题思路
我们考虑每个节点的度数 \(deg_i\) ,如果选为根儿子数就是 \(deg_i\) ,否则是 \(deg_i-1\) 。
所以把环弄出来,枚举一下根,然后考虑叶子数大于 \(3\) 的情况分类讨论一下就好了。
G 相似基因序列问题
题目大意
\(n\) 个匹配串,\(q\) 个询问串,对于每个询问串求有多少个匹配串和它的不同字符的位置不超过 \(k\) 。
\(1\leq n,q\leq 600,|S|\leq 60000,1\leq k\leq 10\)
解题思路
\(k\) 很小,所以我们可以直接暴力枚举匹配串,然后用字符串哈希加二分暴力往前跳到不匹配的地方 \(k\) 次就可以了。
队友用的好像是尺取法。
时间复杂度:\(O(nqk\log |S|)\)
K 四国军棋
题目大意
两个人有长度分别为 \(n\) 和 \(m\) 的序列 \(a\) 和 \(b\) 。
然后两个人轮流取出最前面的数 \(pk\) ,小的被淘汰,被淘汰的那个人继续取数,如果一样就都被淘汰。
谁没数字了就输,求两个人是否能打平。
\(q\) 次操作修改一个序列的一个位置。
\(1\leq n,m\leq 10^5,1\leq q\leq 2\times 10^5\)
解题思路
我们考虑两边取出 \(a\) 和 \(b\) 中最大的数字 \(mx_a,mx_b\),如果 \(mx_a\) 大于 \(mx_b\) ,那么 \(mx_a\) 肯定一路杀穿 \(b\) ,反之亦然,所以要平局肯定要有 \(mx_a=mx_b\) 。
然后如果是这样的话 \(mx_a\) 和 \(mx_b\) 肯定能一路杀到两个相遇,然后后面继续比,而 \(mx_a\) 和 \(mx_b\) 前面的东西就不需要考虑了。
也就是我们只需要考虑一个单调栈(当然相同的数字不能弹掉),用线段树去动态维护一个单调栈就行了。
具体维护方法的话,我们在合并两个单调栈的时候可以向左递归,去查询右边的单调栈会顶替掉左边单调栈的几个位置。
最后顺便用一个字符串哈希去记录单调栈的哈希值,就可以直接比较两个单调栈是否相同了。
时间复杂度:\(O(n\log^2 n)\)
L Mary 有颗有根树
题目大意
开始只有一个根,每次随机选择一个叶子在下面长出 \(M\) 个叶子,重复 \(K\) 次求所有节点的期望深度和。
\(1\leq M\leq 100,1\leq K\leq 10^7\)
解题思路
分别记一下叶子的期望深度和和所有节点的期望深度和就可以递推了。