模拟赛2

2024年了,新开一个模拟赛。

2024.1.2

CWOI

被龙哥吊打了。就只会做一道题,暴力还挂分。但是B题乱写的 \(k=1\)\(30\) 分,乐。

T1 先欧拉筛,然后把每个数分解质因数,顺便统计答案。再做一个前缀和,就能 \(O(1)\) 回答询问了。时间 \(O(n \log n + m)\)

T2 答案是满足单调性的,所以考虑二分答案。check 可以 dp,设 \(f_i\) 表示在前 \(i\) 个大厦中,第 \(i\) 个大厦不修改的满足条件的最小次数。初始时每个 \(f_i\) 都是 \(i-1\)。转移如果有一个 \(j\) 满足 \(\mid h_j -h_i \mid \le(i-j)\times x\),那么就可以把 \([j+1,i-1]\) 中的数修改以满足条件,因此 \(f_i =\min \{f_j+i-j-1\}\)。最后看是否有一个 \(f_i+n-i\le k\) 就行了。\(O(n^2\log n)\)

T3 若选了一个正数,那么和他连成一段的所有正数都会被选,因为这样一定更优。负数同理,因为选负数的目的就是把它两边的正数拼接到一起。于是我们把相邻的正数和负数压成一个数,让数列变成一个正负相间的序列。我们的最优策略一定是把所有正数都选上,若后面那个序列正数个数 \(\le m\) 那么和就是答案,因为根据题意一定有 \(\ge m\) 个正数。否则,我们就要舍弃一些正数,或者选一些负数把正数拼起来,让段数 \(\le m\)。直接贪心就是从小到大排序然后删,但是这样可能不对。因为有可能你把一个正数选了,但是最优策略其实是把他两边的负数一起选然后连起来。因此我们需要反悔贪心,在选了一朵花之后把他和相邻两朵花合并成一朵,如果再次贪心选择到新插入的花,就表示刚才的贪心需要反悔,实则选两段为负的花连接三段为正的花更优。

实现用优先队列和双向链表。

T4 每种符号不满足结合律,所以得换一种方式去思考。可以拆位,每一位互不影响。于是直接用线段树维护每一位从 \(0/1\) 开始,经过一个区间 \([l,r]\) 会变成什么。直接做就是两个 \(\log\),但是如果把每一位放在一起变成一个数就可以 \(O(1)\) 修改,去掉一个 \(\log\) 了。

2024.1.4

CWOI

一分没挂,但是后两题一分没打。

T1 选直径的两个端点,并在他们两个下方每次选最大深度的叶子一定最优。答案就是 \(d+2(m-1)mx\)\(d\) 是直径,\(mx\) 表示从 \(1\) 出发最深的叶子节点的深度。但是有些情况不合法。当树是一条链时,\(1\) 号点是不能扩展的,因此答案就是 \(md\)。还有可能直径的端点是一号点,此时选一号点不优,每次只能多加一个直径,因此要选次长直径去算答案。

T2 非简要题意:构造一种 \(n \times m\) 棋盘上的 \(k\) 子棋平局局面或报告无解。这个真的是非简要题意,简要题意:

一开始想了不能出现 \(k\) 子连,那么就在一个 \((k-1)\times (k-1)\) 的小矩阵里构造,交错放黑子、白子,相邻两个矩阵让他们黑白互换,这样就能保证黑子和白子数量一样。但这样有个问题:边上和下面会剩下来一坨。我直接把边上和下面也按顺序填了,一开始还感觉很对,但后面 rand 了一组数据,有可能会在填边角料时和上面填好的矩阵斜着连成 \(k\) 字,还极不好处理。因此我换了一种构造方式:直接竖着连着放 \(k-1\) 个黑子,再连着放 \(k-1\) 个白子(抵到 \(n\) 了就把 \(n\) 行放完就行),如果 \(m\) 是奇数多出来一列,那就在那一列前面 \(k-1\) 个白 \(k-1\) 个黑的放,最后剩下一小点黑白交错放,看上去很对,因为这样放最多就是多出来那列和前面的连成三子。既然可能连成三子,那 \(k=3\) 就会出锅。比如:

\[01010 \]

\[01010 \]

\[10101 \]

\[10101 \]

\[01010 \]

\[01011 \]

右下角的 \(1\) 就连成三子了。也就这一种情况。如何解决?既然这样 \(n,m\) 不行,不如交换 \(n,m\),用 \(m,n\) 构造就可以了!

2024.1.9

CWOI

T1 直接模拟好吧。

T2 题目保证了序列单调递增,因此可以考虑二分。二分一个 \(mid\),如果 \(a_{mid}<mid\) 那么 \(l=mid+1\),否则 \(r=mid-1\)。至于区间加,分块、线段树、树状数组都可以维护,我写的线段树,时间 \(O(n+k\log^2n)\)

T3 求区间出现次数为奇数的数的个数。离散化,然后莫队板子。

T4 很牛的一道卡特兰数。可以先设 \(f_n\) 表示节点个数为 \(n\) 的二叉树个数,\(g_n\) 表示所有节点个数为 \(n\) 的二叉树的叶子节点个数,那么转移就是 \(g_n=n\times f_{n-1}\)。证明:设节点个数为 \(n\) 的二叉树有 \(a\) 个叶子结点,则分别删去这 \(a\) 个节点,就能得到 \(a\)\(n−1\) 个节点的二叉树。也就是说,我们可以认为这一个 \(n\) 个节点的二叉树对应了 \(a\)\(n−1\) 个节点的二叉树,每有一次对应就会对 \(g_n\) 产生 \(1\) 的贡献。我们的任务转变为求出共有多少次对应。设有 \(b\) 个点有一个儿子的节点,\(c\) 个点有两个儿子,那么有一个显然的结论是:\(a+b+c=n\)。还有一个不那么显然的结论:\(b+2c=n-1\)。这个结论是怎么回事呢?有 \(c\) 个两个儿子的点,于是算上他们的儿子就有 \(2c\) 个,\(b\) 同理。但是因为根节点没有父亲,因此就是 \(n-1\) 个点。然后对于一个 \(n\) 个点的二叉树,还能插得节点个数就是 \(2a+b\) (所有叶子都能加两个,有一个儿子的还可以加一个),根据前两个结论可以得出:\(2a+b=n+1\),因此一棵 \(n\) 个点的二叉树就可以有 \(n+1\) 个位置可以新增节点。那么一棵 \(n-1\) 个节点的树就有 \(n\) 个位置可以新增,每一个位置的增加都会产生一棵新的 \(n\) 个节点的二叉树,因此每一个 \(n−1\) 个节点的二叉树在计算 \(g_n\) 的贡献中都总共被对应了 \(n\) 次,故 \(g_n=n\times f_{n-1}\)

至于 \(f\) 可以通过枚举左子树结点个数得到:\(f_n=\sum\limits_{i=0}^{n-1}g_ig_{n-i-1}\),这就是卡特兰数的公式,于是直接用 \(f_n=\dfrac{f_{n-1}(4n-2)}{n+1}\) 表示 \(f_n\)。由于答案是 \(\dfrac{g_n}{f_n}\),代入 \(g_n=n\times f_{n-1}\),再消去 \(f_{n-1}\),答案就是 \(\dfrac{n(n+1)}{4n-2}\)

2024.1.11

CWOI

T1 首先来思考一条长度为 \(k\) 的路径,假设起点为 \(u\)\(u\) 的下一个点是 \(v\),那么 \(v\)\(1\) 就要走 \(k-1\) 步,因为,每个点只有一条出边,因此到 \(1\) 号点的路径是唯一的。若想要 \(v\)\(k\) 步就到 \(1\),那么必须有一条路径从 \(1\) 出发行走一步又能回到 \(1\),也就是 \(1\) 向自己连边,形成自环。这样对于那些走到 \(1\) \(\le k\) 的点都合法了,因为可以再自环上一直加 \(1\),那么就只需要考虑到 \(1 > k\) 的点了。因为每个点出度都为 \(1\),因此可以把图看作一棵树,\(1\) 的出边不管他,因为把它换成自环了。一个贪心是:对于一个点(从下向上考虑),如果子树中最深的节点的深度和它的深度差刚好等于 \(k-1\),那么把这个点连到 \(1\) 下面去是最优的,这样它子树中的所有点都满足条件了,并且这个数量卡满了,是最优的,于是贪心就完了。

T2 两棵树如果同构,那么他们的深度一定相同。于是设 \(T\) 的直径其中一条直径为 \(a_0 - a_1 - \dots a_{D-1} - a_D\)。则以 \(a_i\) 为根时,树的深度为 \(\max\{i, D - i\}\),于是一共分为了 \(\lfloor \frac{d}{2}\rfloor+1\) 个等价类。而当我们在不断” 加叶子” 的过程中,树的直径不会减少,于是 \(\lfloor \frac{d}{2}\rfloor+1\) 就是颜色数量的一个下界。下面以构造的方法说明,这个下界也是可以达到的。和大多数题一样,我们取这棵树的中心 (直径中点),以它为根。当然,首先还是要根据 D 的奇偶性讨论它是一条边还是一个点。

  1. 树的中心是一条边 \((u,v)\)。此时,将这条边断开后,形成了两棵子树,分别以 \(u,v\) 为根。记 \(b_d\) 为两棵树中,所有深度为 \(d\) 的点中,子节点数的最大值。然后,我们把每个点都补子节点,直到将每个深度为 \(d\) 的点的子节点数都补齐到 \(b_d\)。可以证明,最终得到的树具有高度的对称性,对于每个深度 \(d\),深度为 \(d\) 的所有点都处于同一个等价类——它们都可以被染成相同的颜色。于是最终不同等价类的数目就等于不同深度的个数,而深度的最大值为 \(\lfloor \frac{d}{2}\rfloor\),因此 \(\lfloor \frac{d}{2}\rfloor+1\) 种颜色就足够了。
  2. 树中心是个点,类似,分成两个子树。

接下来考虑,在满足颜色数量为 \(\lfloor \frac{d}{2}\rfloor+1\) 的情况下,叶节点数量的最小值。当中心是一条边时,直径不能再增大,不然会多出来一层让答案变劣。而一个点时,直径可以增大,答案还可能更优,因此要去枚举增大直径的情况,就是枚举当前中心的邻边作为中心边,计算答案并更新就好了,\(O(n^2)\)。具体算叶子个数,可以记录每一层的最大子节点数,答案就是他们累乘起来(如果被边分开了要 \(\times 2\),两棵子树),因为已知了某一层的点数为 \(s\),它下一层的最大点数是 \(mx\),那么把下一层填满就相当于每个当前层的点都会产生 \(mx\) 个儿子,也就是 \(s\times mx\),因此累乘起来便是答案。

T3 朴素 dp 是设 \(f_i\) 表示杀完前 \(i\) 个的最小代价,转移枚举最后一个区间在哪里杀的,\(f_i=\min\limits_{i-k\le j <i}\{f_j+\max\limits_{j+1\le k \le i}a_k\}\)。对于 \(\max\) 相同的一段,因为 \(f\) 单调不降,所以肯定取最前面的 \(j\) 转移,只要能维护出所有 \(\max\) 连续段并求出最大值就行了。可以用线段树做到 \(O(n \log n)\)。更进一步,可以考虑一个单调队列,但是因为要从比自己大的 \(a_j\) 转移过来,所以这个单调队列既要删对首,又要删队尾,最小值不能直接快速维护。于是有一种经典做法是维护一个中点到两边的后缀/前缀最大值,每次删过中点就重构,复杂度 \(O(n)\)

证明大概就是设势能为中点到两端的长度之差,每次 \(\text{push/pop}\) 最多使势能增加 \(1\),当势能到一定值后花 \(O(\text{势能})\) 的时间重构。

2024.1.16

CWOI
打得太烂了吧。暴力打不满,还打挂,被C-组大佬们薄纱了。什么时候能让自己暴力不挂分,并且会打高档暴力啊!看来还要加训思维。

T1 对于一个 \(\text{agnus}\) 思考有多少个区间会包含它。首先考虑左端点 \(l\),在上一个 \(\text{agnus}\)\(\text g\) 到当前的 \(\text a\) 都是合法且未被统计过的,至于右端点直接到 \(n\) 就行了。答案累加他们的积。

T2 赛时一点思路都没有,怎么没往建树方面想?首先一个想法是每次替换都把字符 \(c\) 向字符串中的每个字符 \(v\) 连边,但是这样边数过多,会像龙哥一样被卡成暴力分。于是考虑换一种建树方式,保证只有叶子节点是字符。维护 \(26\) 棵二叉树表示每个字母最后变成什么字符串,建树把读入的操作反过来,按 \(s\) 的顺序进行建树,类似线段树每个点表示一个区间,查询时直接像主席树那样查询,左儿子直接进,右儿子减去左儿子的 size 再进,到叶子输出即可。

T3 很好的一道题。设 \(s\) 为灯的状态,\(t\) 为操作序列,那么一次操作后灯的状态就变成了 \(s \oplus t\)。我们先不考虑操作序列的一个值翻转,只考虑它的位移,假设操作了 \(m\) 次,那么 \(t\) 中一个为 \(1\) 的位置 \(i\) 就会像:\(i \to i+1 \to i+2 \dots i+m\) 这样位移 \(m\) 次,自然会让 \([i,i+m]\) 这个区间全部翻转一遍(注意是首尾相连的循环区间)。再思考操作序列某一个值的翻转,如果在第 \(j\) 次翻转,那么可以改变 \(m-j+1\) 位的状态,并且注意到 \(\oplus\) 是有结合律的,因此把位移和操作序列值的翻转分开考虑即可。

考虑枚举答案为 \(m\),那么位移直接循环右移 \(m\) 位即可,得到 \(t^{\prime}\)。此时只需要看能否用 \(m\) 次操作,第 \(i\) 次可以选一个长度为 \(i\) 的区间进行翻转,把 \(t^{\prime}\) 变成全 \(0\) 即可。这玩意直接 dp 预处理,转移枚举区间长度以及操作序列的状态,得到连续的一串 \(1\),设其为 \(x\),这个 \(x\) 也可以循环位移,对于每个 \(x\),直接 \(f_{i,j} \mid= f_{i-1,j\oplus x}\),初始 \(f_{0,0,}=1\)。求答案去找最小的满足 \(f_{t,m}=1\)\(m\) 就行了。时间 \(O(n^22^n+nT)\)。虽然还能优化,但是 \(4s\) 足够了。

T4 首先注意到最后一定会回到 \(x=0\) 的位置,那么每条边只要你出去了就一定会回来一次,因此每个 \(a_i\) 都是偶数。因此可以把每个 \(a_i\) 先除以 \(2\) 再进行考虑。

首先考虑 \(n=2\) 的两种情况:\(a_1>a_2\)\(a_1 \le a_2\),我们不妨进行一下分类讨论。

\(a_1>a_2\) 时,要想让转弯次数更少,通过贪心可以得知是 \(0 \to 2 \to 0\) 这条路线走 \(a_2\) 次且 \(0 \to 1 \to 0\)\(a_1-a_2\) 次。其他任何的路径都会带来额外的转弯次数,会严格劣于最优解。这样我们就只用考虑这几次的顺序即可,也就是在总共 \(a_1\) 次路径中选择 \(a_2\) 次,结果为 \(C_{a_1}^{a_2}\)

接下来当 \(a_1 \le a_2\) 时会相对复杂一些,需要在 \(1,2\) 两个点之间来回走把多余的次数抵消。由于每次出去必定会对 \(a_1,a_2\) 都产生贡献,所以每对 \(a_1\) 产生一次贡献之后都会对 \(a_2\) 产生若干次(至少一次)贡献。所以我们可以考虑插隔板,把一共 \(a_2\) 个物品分成 \(a_1\) 份,也就是 \(C_{a_1-1}^{a_2-1}\)

考虑完特殊情况,接下来要拓展到一般情况。我们知道 \(a_i\) 可以代表一共有 \(a_i\) 次是在向右走的情况下走到了 \(i\) 点,这个时候到了 \(i\) 点,如果向左走了回去则对接下来不产生影响,否则就和上面 \(n=2\) 的情况一样。所以我们可以局部性的讨论每个点的情况,这样我们只用在意它左右两边的点的情况,因为这具有相对的独立性。

因此,最终答案为

\[\prod\limits_{i=1}^{n-1} \left\{ \begin{aligned} C_{a_i}^{a_{i+1}}(a_i>a_{i+1})\\ C_{a_{i+1}-1}^{a_{i}-1}(a_i\le a_{i+1}) \end{aligned} \right. \]

2024.1.18

CWOI

不会T1 + T2正解没调出来,大概是心态不好 + 思维不到位,现在签到都做不出来,确实该反省一下了。

T1 转化题意就变成对于每个 \(i\),从序列中任意选出 \(k\) 个(可以重复)数,求这 \(k\) 个数的 \(\gcd = i\) 的方案数。因为 \(\gcd \{a_{p_1},a_{p_2},\dots,a_{p_k}\} = i\),因此每个 \(a_{p_j}\) 都能写成 \(ki\) 的形式,也就是 \(i\) 的倍数。我们假设是 \(i\) 的倍数的数有 \(x\) 个,那么从中任选 \(k\) 个的方案就是 \(x^k\)。但是其中有很多方案的 \(\gcd \ne i\),因此需要容斥,用 \(f_i\)\(f\) 为每个 \(i\) 的答案)减去每一个满足 \(i < j \le m,i \mid j\)\(f_j\),这样就去掉不合法情况了。注意倒着枚举。

T2 大家和题解都是离线做法,那我来一个在线做法吧。首先题目保证不出现环,因此整张图可以看做一个森林,那么,要求的就是树上最长异或路径,不就是这道题吗!于是对于每棵树维护一个 trie,接下来就只用合并了。合并的话直接启发式合并,小的往大的上合,每次更新小连通块的每个 \(sum_i\),再把它往 trie 树上加,加的时候同时查询并更新当前连通块的答案,每次 \(O(1)\) 输出即可。

T4 决策单调性。首先可以想一个 dp。先排好序,设 \(f_{i,j}\) 表示走到第 \(i\) 个,推销了 \(j\) 户的最小答案,那么对于每个 \(k\) 的答案就是 \(\min\limits_{i=1}^{n}\{f_{i,k}\}\)。转移枚举一个 \(p\),那么 \(f_{i,k}=\min\limits_{p=1}^{i-1}\{f_{p,k-1}+a_{i}+dis(p,i)\}\)\(a_i\) 提出去就是 \(dis\)。你会发现 \(dis\) 这玩意满足交叉 \(=\) 包含,因此直接决策单调性。换一个贪心柿子,每个 \(i\) 的答案就是 \(\min\limits_{j=1}^{i-1}\{2s_j+V(k,i)\}\)\(V(k,i)\) 表示前 \(k\)\(a_j\) 中前 \(i\) 小的和,使用主席树。直接分治转移即可。\(O(n\log^2n)\)

2024.1.23

CWOI

T2 双 \(\log\) 被卡常,赛后优化成单 \(\log\) 还是被卡常,人傻常数大。T3 还因为神秘原因 RE,T4 写的 \(O(n!m)\) 暴力没分,为什么不写 \(O(n!n^3)\)!!!

T1 赛时脑抽还写了个莫队,OJ上 T 了,还好办公室的机子跑得快。首先一段区间的和要是 \(k\) 的倍数,那么一定会满足两个前缀和 \(\bmod k\) 同余。因此先求出每个前缀和,注意到 \(k\) 只有 \(100\),因此预处理每个 \(k\) 所有的 \(sum_i \bmod k\)。如果区间长度 \(\ge k\),那么一定会有两个位置相同,直接加就行。否则暴力找即可。\(O(nk+Tk)\)

T2 考虑如何判断一个 \(g\) 是否合法,对于每个 \(i\) 有一个区间 \([a_i-k,a_i]\),只要这个区间存在一个 \(g\) 的倍数就把计数器 \(+1\),最后看计数器是否 \(\ge n-f\) 即可。那么我们只需快速算就行了。因为区间长度都为 \(k\),那么一个 \(g\) 的倍数就会对 \([g,g+k]\) 中的每个区间造成 \(1\) 的贡献。但是这样可能会有多个倍数统计到一个重复区间,因此每次只考虑不覆盖下一个倍数的区间,即假设当前的倍数是 \(mg\),下一个倍数就是 \((m+1)g\),那么 \(mg\) 对应的区间就变成 \([mg,\min(mg+k,(m+1)g-1]\)。这个区间的值直接求前缀和就行了。复杂度调和级数 \(O(n \log n)\)

T3 因为询问的两个矩形是不相邻的,那么我们直接用链表维护这个矩形,每次交换就只有两个矩形外面的一圈会被改变,直接更新即可。\(O(n+m)q\)

T4 考虑往两边加元素。假如说现在要加 \(x\),考虑与 \(x\) 有关的所有三元组,(这里只考虑其余两个元素都已经出现过的三元组,这样每一个三元组都会被最后一个被加入的元素唯一的计算)。如果 \(x\) 在三元组的两端,即形如 \(x\) \(a\) \(b\) 的三元组。记 \(pos_i\) 表示 \(i\) 在序列中的位置,如果 \(pos_a<pos_b\),那么 \(A+1\),否则 \(B+1\)\(A\) 就代表 \(x\) 放左边的方案,\(B\) 就是 \(x\) 放右边。\(A\) 大就把 \(x\) 放左边,否则放右边。至于 \(a\) \(x\) \(b\) 这种情况,我们在输入时记录三元组中间的数的出现次数,按这个从大到小排序后选数,这样便保证了不会出现中间的数在旁边两数出现后再出现的情况。至于为什么答案能顶到 \(\lceil \frac{m}{2} \rceil\),因为每次选方案数大的那个放,所有三元组都会被遍历到,因此最后满足条件的一定大于等于 \(\lceil \frac{m}{2} \rceil\)

2024.1.25

CWOI

\(100 + 100 + 20 + 20 =240\) 侥幸拿下标准分,可惜三个大佬去 WC 了,不计入评分/kk。

T1 终于有普及组题了,等差数列求和。

T2 给定一个数 \(n\),要求你从 \(1 \sim n\) 选出尽可能多的数使得任意两个相邻的数的最大公约数大于等于 \(2\)。首先把全部偶数选上,接下来考虑插入一些奇数。一个直接的想法是让奇数插在两个偶数之间,这样接壤的地方都是偶数。我们可以枚举每一个质数,把这个质数的倍数放进去。但是为了他的倍数至少有两个偶数,需要先判掉一些数。首先是 \(2p \le n\)\(3p>n\) 的数,你最多选两个放,一个头一个尾。不然相交的地方一定是互质的,不满足条件。接下来就是 \(3p \le n\)\(4p > n\) 的数,每个 \(p\) 可以放 \(p,2p,3p\)。注意到他和 \(2,3\) 有关,因此把他们塞在 \(2\)\(3\) 中间即可。我是放在了 \(6\)\(3\) 中间,即形如 \(6,2p,p,3p,3p^{\prime},p^{\prime},2p^{\prime},\dots\) 这样一直交替放下去,是能满足条件的。最后就是 \(4p \le n\) 的数,他们一定有至少两个偶数倍数,把他们放两边和其他偶数接壤即可。

T3 维护每个组每个人一开始的起始位置。每次来人若 \(k>0\),相当于所有组的位置 \(+k\);否则相当于全体 \(\times 2\)。把这些操作用线段树维护,形如 \(kx+b\),而 \(x\) 就是起始位置,直接根据操作的编号就能知道,那么 \(2\) 操作就能解决了。对于 \(3\) 操作,相当于倒着操作回去,把所有连着的 \(+k\) 看成一个操作。若当前是 \(\times 2\)\(x\) 还是奇数,那么说明这是一组无限的人的组,直接输出当前编号即可。偶数那就接着 \(\div 2\)。若是 \(+\),因为压成了一段,那么看这段的和是否 \(<x\),小于就说明还在前面,用 \(x\) 减去这段和。否则就说明在这段中,二分一个后缀即可。

2024.1.27

CWOI

不计入排名的场总是打得非常好。。。

T1 对于每个 \(i\),相当于找一个 \(i \le r \le n\) 使 \(s_r\) 最大,$1 \le l <i $ 使 \(s_l\) 最小,他们相减就是包含 \(i\) 的最大子段和。维护一个前缀 \(\min\) 和后缀 \(\max\) 即可。

T2 每个点向比他大二的数字连边,就形成了一个 DAG,根据起点的定义,就是入度为 \(0\) 的点,这不就在暗示我们拓扑排序吗?先不考虑长度的限制,设 \(f_u\) 表示到 \(u\) 的路径数,初始时入度为 \(0\) 的点赋值成 \(1\)。转移就是拓扑的时候 \(f_v =f_v+ f_u\),最后累加出度为 \(0\) 的点的答案即可。但是这样并不保证长度 \(\ge 4\),于是我们需要减去长度 \(<4\) 的路径。对于每个起点直接去暴搜,因为它最多有 \(4\) 条出边,连向的点又最多只有 \(3\) 条出边,因此最多枚举 \(12\) 条路径。复杂度 \(O(nm)\)

T3 先考虑不能被 \(4\) 个多米诺骨牌顶点覆盖这个限制。这个限制等价于,当两个 \(1 \times 2\)\(2 \times 1\) 的多米诺并排时,其两者的交点会相应的产生两个能覆盖交点的多米诺,如下图所示:

只有这样才能使顶点不被 \(4\) 个覆盖。接着我们考虑对于一个 \(n \times m\) 矩形,多米诺具有怎样的分布。对于矩形的左边缘或上边缘,其多米诺一定存在下图的分布:

两者显然是等价问题,因此我们只考虑左图的分布。假设存在一种分布使左边的一列全是竖着的,那么按照上一个推论,第二列的头尾就必会空出来一格,这一格只能被横着放。放完后把图旋转一下,就会等价于这种情况了。我们可以结合最开始的限制得到如下的结果:

现在中心空的那两格可以有两种放法,一是直接放竖着的一条,而是放两条横着的,得到以下两个结果:

这个结果表明,只要我们确定了边缘的分布,最后都能填满成一个矩形。但这依然不能解决这道问题,我们不妨扩展一下这个矩形的边界:

我们会发现其边缘是按照对角线扩展的,同时如果利用一个更大的矩形去涵盖原矩形的话,其对角部分会剩余奇数个格子。这表明无论如何填补,都无法填满。有了这个性质,就说明 \(n \times m\) 的大矩阵一定是由若干个 \(n \times k\) 的小矩阵覆盖而成,那么就是一维 dp 了。

假设 \(n \le m\)。首先把 \(n \times m\) 是奇数的情况判掉。对于 \(n=1\),只有一种放法。对于 \(n =2\),可以竖着放一条,也可以横着放两条,dp 一下即可。其他情况可以按照上图构造矩阵的方法,可以发现它一定是长为 \(1,n-2,n\) 的矩阵交替排布的,\(1\) 可以和 \(n-2,n\) 接壤,\(n-2,n\) 不能接壤。dp 即可。

2024.2.1

CWOI

不会T2/kk。

T1 赛时猜了一手结论,结论是错的,但是歪打正着过了。先将所有的数字排序。枚举平均数的位置,假设 \(a_i\) 是第一个能被选的数字。我们需要选尽量多大于等于 \(a_i\) 的数字满足平均数小于 \(a_i\),于是只要考虑尽量多的选取一个前缀即可。

T2 考虑对于一条非树边有什么限制。假设它连接了 \(u,v\) 两点,那么 \(u,v\) 两点在树上的路径就会和这条边构成一个环。这条非树边就要比环上除自己的所有边都要小。不然就会删去比他大的边让他成为树边了。于是按照输入顺序去更新每条边,便能做到 \(O(nm)\)。至于正解,树上两点的路径问题,直接上树剖,把每条树边赋值成第一条会覆盖它的非树边的编号、然后按照读入的顺序,若当前是树边且未得到权值,就把当前剩下最小的权值给它。否则枚举这条非树边的所有覆盖树边,只要满足他们的编号 \(>\) 当前边的编号就赋值。

T3 最后肯定是删除经过某些位置的所有区间,于是设 \(f_i\) 表示当前切到 \(i\),留下的区间的最大权值。答案就是所有区间的权值减去 \(f_{cnt}\)\(cnt\) 是离散化后的总数)。转移枚举上一个切的点 \(j\),只保留 \([j+1,i-1]\) 中前 \(k\) 大的区间。至于实现,倒着枚举 \(j\),用一个小根堆维护即可。

2024.2.3

CWOI

过完寒假才来补的

T1 先写一个用 set 转移的 dp,时间过不去,发现求 \(\rm {mex}\) 直接 bitset 即可。复杂度 \(O(n^2)\)

T2 对于每个未被覆盖的数,把他们的倍数全都覆盖掉。最后看有多少个覆盖其他数的数。复杂度调和级数 \(O(n \log n)\),注意特判 \(n=1\)

T3 \(n \le 26\) 提示我们要状压。一个直接的想法是设 \(f_i\) 表示状态为 \(i\) 的最大独立集大小,转移考虑枚举每个为 \(1\) 的位置 \(j\),从 \(f_{i \oplus 2^j}\) 转移,可以预处理每个点和他相邻的点集,只有满足 \(i \oplus 2^j\) 的每个 \(1\) 位置在 \(j\) 对应的点集中都没有出现,才能 \(+1\),否则直接继承。直接做是 \(O(n2^n)\),貌似过不去,但是 struct_sec 大佬优化了一下,把找 \(1\) 的过程用 lowbit 优化,就能草过去了。正解:观察一下可以发现:只用随便取一个为 \(1\) 的位置转移就行了,并不需要枚举每个位置。因为假如新加一个点后 \(i\) 的最大独立集是变大了的,那么从另一个位置也一定能使 \(i\) 变大,效果是一样的,故直接从 \(lowbit(i)\) 转移即可。

T4 考虑枚举矩形的下边界,不断抬高其上边界,那么就是不断有新的点加入现在需要知道当前一个横坐标区间内的所有点在纵坐标某个区间的最大权值和,可以考虑用线段树维护。线段树的每一个节点就是表示一个纵坐标区间,每一个节点维护信息包括从左边开始的最大值,从右边开始的最大值和整段中某一个区间的最大值。更新时把当前横坐标上的所有点单点加入即可。

2024.2.20

CWOI

当了一回大样例老哥,大家 T4 都没输出大样例,我直接多拿 \(10\) 分。

T1 最大值最小二分答案,去看 $\sum\limits_{i=1}^{m}\lceil \frac{mid}{a_i}\rceil $ 是否 \(\le n\) 即可。

T2 相当于一个括号序列,不过要求降低了,只要保证每个位置的前缀和 \(\ge 0\) 即可。从前往后找 \(0\) 的位置,去看他后面最小的前缀和是否 \(>0\),是就放 \(1\),不是就放 \(-1\),线段树维护一下就好了。当然倒着贪心就能 \(O(n)\) 解决。

T3 考虑二分答案,去看是否有 \(\ge k\) 个数 \(\ge mid\)。对于已经 \(\ge mid\) 的数不管它,其他数去看他至少要加上等差数列的哪一项才能 \(\ge mid\),接着就可以倒推出数列起点的合法区间,把这个区间整体 \(+1\),代表这些点作为起点可以多增加一个数。最后看是否有一个点的数量加上 \(\ge mid\) 的数的数量 \(\ge k\) 即可。

T4 在一个人想去的两条城市之间连边 \((a,b)\)。假设每个人一开始都去 \(a\)。用一个 \(cnt\) 记录每个城市人数的奇偶性,假如要反转一个人去的城市,那么可以有以下几种变化:

\[(0,0) \to (1,1) \]

\[(1,1) \to (0,0) \]

\[(0,1) \to (1,0) \]

\[(1,0) \to (0,1) \]

其实就是要么反转一对 \(0\)\(1\),要么 \(0,1\) 交换位置。因此对于一个连通块,若他有 \(x\)\(1\),一定能变成 \(x \% 2\)\(1\)。用并查集算一下就好了。

2024.2.23

CWOI

T3 是 \(1.11\) 的 T4,但是我没改。赛时大家都在研究 T3 题解,只有 yd 写出来了 /bx。但是 MLE,再加上他 T1 权值线段树有个地方写假了,痛失 \(rk1\)

T1 我的做法好麻烦啊。考虑枚举中间的数是什么。假如说中间的数为 \(x\),当 \(x \ge 0\) 时,他右边的数 \(z\) 也一定 \(>0\),就只用考虑 \(x\) 左边的数。先去找到序列中 \(x\) 左边的数中 \(x\) 的前驱为 \(y\),若 \(y \ge 0\),那么直接 \(xyz\) 最大。否则就不能选 \(z\) 了,因为结果一定为负数,所以要让绝对值尽量小才行,故需要找到序列中 \(x\) 右边的数中 \(x\) 的后继 \(z^{\prime}\),答案为 \(yxz^{\prime}\)\(x<0\) 同理。

T2 对着大样例找规律,成功过掉。正解:考虑 \(k=3\) 的一种构造: \(\text{aababacbabaa}\),先分析其下节,设 \(C_i\) 表示第 \(i\) 个字符的出现次数,那么一定有 \(C_{i}\ge C_{i-1}+3\)(因为因为前两个字符和最后两个字符一定是最小的字符,且每个 \(i-1\) 字符之后一定会有一个 \(i\),不然数量就被追上来了)。然后我们发现这个下界的分析也直接导出了一种构造方法:在前面和后面插入两个最小的字符, 每个次小的字符后面插入一个最小的字符,可以通过归纳证明,这种构造方案,在长度固定为下界的情况下是字典序最小的。对于不到 \(n\) 的串,在前面加 \(\text a\) 即可。

T3 关于直径问题,可以将直径中心拿出来研究。但是对于不同的奇偶性,中心有可能是边也有可能是点,因此需要转化一下:把每条边 \((u,v)\) 变成 \((u,e)\)\((e,v)\),这样直径中心就一定在一个点上了。问题就变成每次可以使原来的其中一条边长度增加 \(2\), 使得 \(\frac{d}{2}\) (即半径)最小。考虑枚举中心点,假设从这个点出发能到的最远的点距离为 \(R\),这个点一定是个叶子,那么把这个点到其他叶子的距离都变成 \(R\) 所需的最多操作就是 \(\dfrac{\sum\limits_{v \in leaf} R-dis_v}{2}\)。这时我们再设一个 \(f\) 数组,\(f_i\) 表示最多几次操作能让半径为 \(i\)。通过上式加上一个简单换根 dp 即可预处理出。同时 \(f_i\) 还可从 \(f_{i-2}+leaf\) 转移而来,\(leaf\) 为叶子数量,相当于把每个叶子往外长 \(2\),半径就增加了 \(2\)\(f\) 数组一定是单调的,因此可以把询问离线下来,从小到大排序,同时用一个指针在 \(f\) 数组中单调的走,如果有个 \(f_i \ge k\)\(f_{i-1}<k\) 那么 \(k\) 的答案就是 \(i\)。但如果把我们预处理的 \(f_{n}\) 都走完了,\(k\) 还有余,那么我们就考虑把剩下的 \(k-f_n\) 次操作往叶子上加,为了直径最小,肯定会把每个叶子依次操作,那么半径的增长就为 \(\lceil \frac{k-f_n}{leaf} \rceil\),答案便是 \(n\) 加上增长量。由于奇偶性的问题,还要和操作 \(k-f_{n-1}\) 次取 \(\min\)

T4 暴力 dp,考虑按顺序去填每个 \(c_i\),设 \(f_{i,b_1,b_2,S}\) 表示现在该填第 \(i\) 个数,前一个数是 \(b_1\)\(b_1\) 的前一个是 \(b_2\),当前填完的状态为 \(S\),转移枚举当前填谁,再看一下是否合法即可。然后你发现记忆化一波就过了。题解的证明:首先树上每个点度数一定都 \(\le 4\) 否则一定不存在合法的解。我们考虑对于一个状态 , 如果将树上点 \(b_1\) 和点 \(b_2\) 删掉,那么剩下的森林里每棵树要么全在 \(S\) 里,要么全不在 \(S\) 里。如果不满足这个条件,就会存在一个被染上 \(\le i-2\) 编号的点与至少一个没染色的点相邻,但是之后染色的所有点编号都是 \(>i\) 的,所以一
定无解。分析之后 \(S\) 合法状态最多只有 \(2^C\),其中 \(C=7\) 是连通块数量。复杂度 \(O(n^22^C \log n)\)。这个 \(C\) 确实有点迷,没看懂(

posted @ 2024-01-07 19:47  SunsetLake  阅读(39)  评论(1编辑  收藏  举报
-->