过年至 2.18 的比赛补题

近期题选

2.16 联考

T1

下饭。

对着错的大样例虚空调错 1h,然后清了一下谷歌缓存,重新下载大样例。

下文记文中集合为 \(G\)

\(15pts\)

看到出现次数,不难联想到 kmp。每次 kmp 的时间复杂度是 \(O(|G|\times|S|+\sum _{P \in G}|P|)\) 的。总时间复杂度不难证明是 \(O(q^2L\)) 的,严重跑不满。所以实际上跑到了 \(30pts\)

\(50pts\)

我们发现,每次 kmp 计算 \(G\) 内每一个字符串的 border 数组是重复步骤。所以我们在将字符串加入集合时,就计算好 border。这样每次问询的时间复杂度就变成 \(O(|S|+|T|)\)。时间复杂度是 \(O(qL)\)。实际跑不满,所以不但可以过 \(\max\{q,L\} \le 20000\),甚至可以过若干 \(\max\{q,L\} \le 3\times 10^5\) 的若干点。实际得分:\(60pts\)

\(100pts\)

机房老哥拿 SAM 过了。/bx。

先考虑 lcp 有没有什么神秘做法。然后仔细思考一下,应该没有。

所以把所有串反转,将 lcp 转化为 lcs。

然后字符串题,我们考虑建 ACAM。

(认真学一下 ACAM 再滚回来写)

T2

获得了高达 \(1pts\)。myee 好会嘲讽人哦。

一看题解,前置知识部分不会,所以摆一下。

T3

36s 时限 /xia

50~55pts

问题显然可以转化为有多少个集合的 \([\max L,\min R]\) 不为空区间。

写了个常数飞天的算法,但是没挂分。因为你往 set 里加就可以了。时间复杂度是 \(O(nq\log q)\) 。实际复杂度偏大。过了 \([1,55]-[36,40]\) 的点。

如果拿线段树或者可删堆之类的维护,估计可以拿到 \([36,40]\) 的分数。

65~70pts

然后我们考虑 \(n\le 3\times{10^5},q\le 1000\)。显然,有用的左右端点集合不超过 \(2q\) 个。所以需要考虑的集合个数变成了 \(\min(2q,n)\) 个。拿上述算法维护即可。

90pts

只需要额外实现 \(o=1\)\(o=2\) 的情况。

先考虑 \(o=1\)

考虑一个集合可能会在某个时刻以后变得不优秀,因为没有撤销操作,所以变得不优秀是不可逆的。(也即,只要变得不优秀了,就不会重新优秀了)所以每个集合不优秀的时间可以用时间轴线段树来维护。

具体的,维护一个时间轴线段树,来描述每个时间点处多出的操作,然后线段树上二分,用 BIT 统计答案即可。

\(o=2\) 相当于 \(o=1\) 的做法,但将时间轴倒置。

分块做法摆。

2.17 联考

T1

\(m=0\) 的情况等价于求逆序对,下文记原逆序对数为 \(A\)\(p\) 的逆数组是 \(p'\)(随 \(b\) 的变化而变化)。

剩下除了暴力的部分分都不是很好拿。因为不会有人只是不会线段树。

考虑如何快速求 \(f\)

我们先将问题转化为 \(m=1\) ,且只求一组 \(f\) 的情况。设 \(g_x\) 为添加 \(x\) 增加逆序对数量的最小值。这个东西显然可以快速用扫描线+线段树求出。

然后考虑求 \(f(a[],S)\)(但不保证 \(m=1\)),这样的话答案是 \(A+\sum_{x\in S} g_x\)。证明我会了但我懒得写了。

然后我们考虑如何统计答案。设 \(h_x\) 表示 \(x\) 位于 \(b_{p'_x}\)\(b_{p'_{x+1}}\) 之间的 \(g_x\)(依然可以用线段树求出),这个东西会被统计 \(\sum^m_{i=1} \binom {m-i+n}{n}=\binom{m+n}{n+1}\) 次。答案就是上式乘上 \(\sum h_x\),加上选的方案数\(\times A\) 的结果。

T2

在贪心以后,我们发现每一个庇护所对应的老鼠一定是一个区间,这样我们有了 dp 的条件。
剩下的牵扯决策单调性 dp。复习。

反正不管是写爆搜还是写随机化,都可以轻松拿到 \(20pts\)。如果能意识到上述的 dp,似乎 \(40pts\) 也比较好拿。

T3

全身上下都是暴力分的题,设 \(\sum^T_{i=1} M_i=S\)

Subtask 1 (10pts)

枚举 \(A\) 的所有子串,与 \(B\) 暴力比对。

时间复杂度 \(O(n^2S)\)

Subtask 2 (30pts)

考虑 \(B\) 的抽象含义。设 $|B|=m $。

\(a_{[j+1,j+|B|}\)\(B\) 相似的本质条件是,\(\forall 1\le i \le |B|\)\(a_{[j+1,j+|B|}\) 内存在恰好 \(b_i\) 个小于等于 \(a[j+i]\)

树状数组简单题。不管是每次清空树状数组算还是增量式修改,都可以过。

时间复杂度 \(O(nS)\),事实上增量式的算法可以过两个 \(T,N,S \le 3\times 10^5\) 的点。

Subtask 3 (40pts)

显然,如果 \(B\) 递增,则答案为 \(n-M_i+1\)

反之,为 \(0\)

时间复杂度 \(O(n+S)\)

Subtask 4(50pts)

显然,这个问题可以转化为求 \(a\) 有几个长度为 \(M_i\) 的上升(未必极长)子串。考虑如果存在一个 \([l,r]\) 的上升子串,则一定包含了 \([l+1,r],[l+2,r],\cdots,[r,r]\) 这样 \(r-l+1\) 个上升子串。也就是长度在 \([1,r-l+1]\) 内的子串都应当 \(+1\)。可以用树状数组维护。时间复杂度 \(O(n\log n +T)\)

Subtask 5

我没有优秀做法。其做法已经与正解做法相差无几。

Subtask 6 7 (80pts)

容易发现,我们只用枚举 \(a\) 不超过 \(\max M_i\) 长度的子串即可。我们可以预处理所有 \(a\) 长度不超过 \(10\) 的子串,将这个子串对应的排列扔进 map 里(如果哈希完再扔会优雅很多,常数也会小很多)查询可以 \(O(1)\) 查询。

\(\max M_i=P\)

时间复杂度 \(O(nP^2\log(nP)+L)\),由于是两秒题而且大概率跑不满,所以实现也不用很精细。

Subtask 8(100pts)

考虑将判断相似的过程拟为字符串匹配。所谓的失配即判断将新的一位加入后还是否相似。如果 \(T=1\),可以类似套用 KMP,反之可以类似套用 AC 自动机。

所谓的 还是否相似,也就是判断 \(B_{i+1}\)\(B_{i-p,i}\) 内的排名是否与 \(B_p+1\)\(B_{1,p}\) 内相等。这很好判。

DTCPC

B

考虑什么串可以让答案变小。

10101 可以变化为 010101 的个数减少了一个。

这种题最难处理的一般是“连锁反应”,考虑什么时候会出现连锁反应?

只要不出现两个连续的 0,都可以连锁反应。

也就是,所有不全为 1,且不出现两个连续的 0 的串都可以化作一个 1,代码很短。

C

长度越小结果最优,根据样例的提示:得到括号序列短且多的是:()()()() 的情况,若有 \(n\) 个括号,则有 \(\frac{n(n+1)}2\) 的贡献。

问题转化为构造一个数组 \(a\) ,使得 \(\sum \frac{a(a+1)}2 =k\),且 \(2\sum a\) 最小。可以用 dp 解决。

对于一个 \(k\),可以从所有 \(a\),满足 \(k-\frac {a(a+1)} 2 \geq0\) 转移。这样的 \(a\) 的个数是根号级别的。

所以时间复杂度是 \(O(n\sqrt n)\)

构造可以用 dfs 来构造。

D

机房老哥 KnownError_ 在打比赛的时候说是若只题,我不会。

恶补一下序列分治。

序列分治典中典题是 abc282_h。

一句话来说,区间问题 \([L,R]\) 被转化为 \([L,mid]\)\([mid+1,R]\) 问题,我们需要在 solve(l,r) 内统计所有跨过中点的贡献。问题被简化为了,如何求解一个区间所有跨越中点的区间的子区间的贡献,\(\log n\) 的时间复杂度将问题严格弱化

然后我们可以在 \(O(n)\) 的时间内求出 \([l,mid]\)\([mid,r]\) 区间的信息。考虑一个最大值在什么时候成立。如果 \(t\)\([l,mid]\) 的最大值,我们可以二分出 \([mid,r]\) 内最接近 \(mid\)\(val_x \ge t\),则 \(t\)\(x-mid+1\) 个区间做贡献。 \([mid,r]\) 区间同理。

考虑到序列分治和二分双重的 \(\log\),时间复杂度是 \(O(n\log^2 n)\)。两个 \(\log\) 都是小常数,实际跑的非常快。

H

考虑操作次数显然不会超过 \(2\)。一定选择最小的 \(a_i+a_j\) ,两次操作后一定可以构成一个环。

考虑操作次数为 \(1\) 和本身就有环的情况。

考虑从 \(i\) 连边,一定连到他可以连的点里 \(a\) 最小的。

可以用拓扑排序维护。

J

考虑任意一位操作偶数次都是没有意义的。

考虑最后的形态,我们希望最后的形态一定是 0 在前,1 在后,且都占据整个字符串的一半。

如果出现一个 1,我们的一步操作可以使得这个 1 往后一位。

例如:1000 反转前两位后变成 0100,再反转第二位第三位可以变成 0010

如果遇到两个连续的 1,就可以全部化作 0。这样的话最后的形态一定是末尾有 1 个或 0 个 1,然后我们再从后往前将若干个 00 转化成 11 即可。

然后这个步骤不难发现,至多需要 \(n+\frac n 2=1.5n\rightarrow 3\times 10^5\) 次。不符合要求。再考虑 考虑任意一位操作偶数次都是没有意义的。 这一说法,我们将操作序列去重即可。因为去重后的序列每一位数只有出现和不出现两种选择,一定 < n。

L

没有字符出现大于两次,则字符串至多有 \(2\times 26=52\) 位。我们枚举原来的字符串所有长度不超过 \(52\) 的子串。时间复杂度 \(O(52n)\)

M

考虑不寻常的数据范围。

\(n\le 5\times 10^4\) 可以猜测,解法的时间复杂度是 \(\frac {n^2}w\),也就是使用 bitset。

然后我们发现 \(L,R\) 的范围非常大,但是事实上可以用到的非常少。

  • 如果 \(a\) 内有重复的数,答案一定为 \(0\)

  • 反之,对于 \(k\ge \max a_i\),这样的 \(k\) 一定合法。我们发现 \(a_i \le 4\times 10^5\)。所以需要的考虑的 \(R\) 也只有 \(4\times 10^5\)

问题已经转化成 \(1\le L \le R \le 4\times 10^5\) 的情况。后文记 \(\max a\)\(A\)

然后我们考虑怎么用 bitset 维护这个信息。

我们发现任意一组 \((a_i,a_j)\bmod k\) 相等,当且仅当 \(k|a_i-a_j\)。所以,我们维护 \(a_i-a_j\)\(a_i-a_j\) 的约数。

维护 \(a_i-a_j\) 的约数,复杂度变成了 \(n^2\sqrt A\),显然过不了。我们考虑反过来考虑,对于一个数 \(k\),如果存在正整数 \(p\),使得存在 \((i,j)\) 满足 \(a_i-a_j=pk\)。则 \(k\) 不满足要求。而维护某一个数的所有倍数,这是一个调和级数:\(\frac A 1+\frac A 2+\frac A 3 + \cdots + \frac A A \approx A\log A\)

然后,我们考虑做差怎么用 bitset 维护,这是一个经典 tricks。先将所有 \(a_i\) 标成 1,这个 01 数组记为 \(G\),然后固定 \(i\) 的所有 \(a_j-a_i\) 所构成的 \(01\) 数组即为 G 右移 \(a_i\) 位的 bitset,这一步的时间复杂度是 \(O(\frac n w)\)。对于每一个 \(a_i\) 都如此维护,即可得到我们所要的 \(a_i-a_j\) 构成的 01 数组 \(G'\)

对于一个数 \(k\),枚举其在 \(4\times 10^5\) 内的所有倍数 \(pk\),如果有 \(G'[pk]=1\) ,那么 \(k\) 也不合法,因此 \(G'[k]=1\)

然后不管用 count 还是枚举转化过的 \([L,R]\) 暴力计数都可以。对于所有 \(G'[k]=1\)\(k\) 即代表 \(k\) 不合法。

有一些细节。

think-cell Round

A

排序后选择所有下标为奇数的位。

B

构造 n 1 n-1 2 n-2 3 ... 的序列即可。

C

按照 \(b_i=a_i+i\) 从大到小的顺序取。取到 \(b_i\) 的时候,如果 \(b_i>b_{i-1}-1\),则 \(b_i\) 一定只能在 \(b_{i-1}-1\) 的时候才能取。

D1

枚举子串,考虑 \(f\) 如何求。

考虑选择的 \(q_{[l,r]}\) 一定长度为 \(2\),所以构造大概是 1001001 这个样子。

考虑一个贪心:

  • 对于 \(s_i\),如果我们已经将 \(q_i\) 标为 \(1\),则 \(q_i\)\(1\)
  • 对于 \(s_i=1\),如果 \(q_{i-1}\)\(1\),则这一位为 \(0\)
  • 对于 \(s_i=1\),如果 \(q_{i-1}\) 不为 \(1\),则标记 \(q_{i+1}\)\(1\)

最后统计 \(q_i\)\(1\) 的个数即可。时间复杂度 \(O(n^3)\)

D2

考虑 dp。倒着 \(dp\),设 \(f_i\) 为以 \(i\) 开头子串的 \(f\) 的和。

考虑新增一个字符对答案的影响。

如果 \(s_i=1\),则我们需要在 \(q_{i+1}\) 标记为 \(1\),这会对以 \(i\) 开头的 \(n-i+1\) 个子串造成影响,但 \(s_{i+2}\) 所造成的代价就不用考虑了,因而 \(dp_i=dp_{i+3}+(n-i+1)\)

反之,什么也不用做,\(dp_i=dp_{i+1}\)

答案是 \(\sum^n_{i=1} dp_i\)

E

组合数题。输。

考虑什么情况下可以达到最终情况。

考虑一个布尔数组:\(s_i=0\) 表示没有保留 \(i\),反之表示保留了。

结论是 \(s\) 合法当且仅当存在 \(s_i=0\) 满足 \(s_{[1,i-1]}\) 存在至少 \(k\)\(1\),且 \(s_{[i+1,n]}\) 存在至少 \(k\)\(1\),且 \(1\) 的个数是 \(2k\) 的倍数。

枚举 \(k\) 和剩下元素的数量 \(x\),答案为 \(\binom{n}{x}-\binom{x+2k-1}{x}\)。加起来即可。

由于 \(x\) 的数量是反比例形式的,根据调和级数,时间复杂度为 \(O(n\log n)\)

ARC172

A

考虑任意一个 \(2^i \times 2^i\) 的方块可以拆分成四个\(2^{i-1} \times 2^{i-1}\)的方块。

我们考虑 \(h\times w\) 的方块可以如何拆分为若干个边长为 \(2\) 的次幂的正方形。不妨设 \(h>w\),则我们考虑最大的 \(2^i \le w\),这样就拆分成了 \(\frac h {2^i}\)\(2^i\times 2^i\) 的方块和 \(h\bmod 2^i,w\) 的长方形边角料和 \({w-2^i,h-h\bmod 2^i}\) 的长方形边角料。

不断分治下去,我们将原来的长方形转化成了若干边长为 \(2\) 的次幂的正方形。从大到小考虑,先去满足大长方形数量的要求,剩余的就转成四个小一号的正方形。

这样判断下去,如果某一个大小的正方形不够了就是 No

时间复杂度的证明方式同辗转相除法,是 \(\log h\times w\) 级别的。

B

考虑不存在两个相同的长度为 \(k\) 的子序列的条件。如果两个字符之间可以互相替代,那么就一定存在。“替代”具体的条件也就是对于任意的 \(s_i=s_j\),如果不使用任意字符 \(s_k\) 满足 \(i<k<j\) ,就可以构成长度为 \(k\) 的字符串,那一定可以互相替代。

也就是对于任意两个相同字符,他们之间的距离至少是 \(n-k\)

然后一开始是 \(L\) 种选择,从第二位开始选择的数量逐步递减,直到第 \(n-k+1\) 位,这时候第一位选择的那一个字符就又可以用了,此时选择数开始持平,直至结尾。乘起来即可。

C

没写完。输。

我们考虑假设将 \(a_1\) 放在 \(a_x\)\(a_{x+1}\) 之间。因为 \(a_1 \sim a_x\) 都已经投票完毕,所以对于 \(a_{[x+1,n]}\) 的字符串与原来相比不会变化。

而前面的投票结果可以增量式维护。从 \(a[2]\) 开始维护 Win/Draw/Lose 即可。然后这个问题就变成了字符串拼接本质不同的个数。最好的方法是哈希完扔 map,然后很失败没写完。

D

神仙题。

\(<\) 不好计算,先试试 \(=\)

构造方法有

\[p_1=\{1,0,0,\cdots,0\} \]

\[p_2=\{0,1,0,\cdots,0\} \]

\[\cdots \]

\[p_n=\{0,0,0,\cdots,1\} \]

因为是小于号,我们可以给每一项加一个很小的 \(eps\)

考虑到这个 \(eps\) 很小,他的平方项不用计算。

\[d(x,y)=\sqrt{2-2(\epsilon_{x,y}+\epsilon_{y,x})} \]

到这里,构造方法已经很显然了,越后输出的越小即可。

posted @ 2024-02-29 15:00  wtcqwq  阅读(23)  评论(0)    收藏  举报