2021.5 省队集训
Day1
A
题目:https://codeforces.com/gym/102978/problem/I。
首先,考虑一个序列 \(a\) 长度为 \(m\) 的字典序最小的子序列 \(x\) 有什么性质:
- \(x_1\) 一定在 \([1,n-m+1]\) 中,且是这个区间内的最小值。
- \(x_2\) 一定在 \([2,n-m+2]\) 中,因为 \(x_1\) 是 \([1,n-m+1]\) 的最小值,所以假如 \(x_2\) 在 \([2,n-m+1]\) 中,它一定大于 \(x_1\)。换句话说,若 \(x_2<x_1\) 它一定在 \(n-m+2\) 处。
- 以此类推。
所以,在 \(x\) 中只要有一个“拐点”,使得前面单调递增,后面不一定单调递增,那么不一定单调递增的部分就一定是 \(a\) 的后缀。
所以只需要对前面单调递增的部分进行计数即可。
B
题目:https://codeforces.com/gym/102992/problem/J。
我们考虑这个操作 \(2\)。令 \(x=a_l\oplus a_{l+1}\oplus \dots \oplus a_r \oplus x\),它需要满足初始局面先手必胜(\(x \neq 0\))以及操作一次以后先手必败。如果一个 \(i\) 满足 \(x \oplus a_i < a_i\),那么可以让这一堆石子剩下 \(x \oplus a_i\) 个。
考虑什么情况下满足 \(x\oplus a_i<a_i\)。可以发现当且仅当 \(a_i\) 在 \(\mathbf{highbit}(x)\) 上为 \(1\)。
于是需要写一个数据结构,可以:
- 区间赋值 \(\max\);
- 区间查询异或和以及在某一位上为 \(1\) 的个数。
操作 \(1\) 是 segment tree beats 的经典操作,每个区间记录一个“加”的懒标记即可。
考虑到操作 \(1\) 的特殊性(每次只会将所有区间最小值增加一个值),每次下传标记的时候撤销原来区间最小值的影响,再计算新值的影响即可。
Day2
A
一种比较蠢的方法是树形 dp。
我们可以发现,对某个非叶子节点执行一次操作,相当于允许它的子树内的某个叶子节点不进行操作。
于是设 \(f_i\) 为 \(i\) 所在的子树内的最小代价,\(g_i\) 为允许一个叶子节点不进行操作的最小代价。
记录每个 \(f_i,g_i\) 的决策,最后给每个操作随机赋一个值即可。
但这样无法通过,因为随机赋值的值域是 \([1,10^9]\),这种范围内随机选值冲突的概率很高(生日悖论)。
我们可以强制让节点的随机值与它的编号有关,这样能提高正确率。
代码:https://paste.ubuntu.com/p/SmbCMvjk22/。
B
由于字符串是随机生成的,而哈希也是一种随机的操作,所以哈希值在 \([0,m-1]\) 中类似于均匀随机分布。
听 qyc 说比较显然地有 \(\Theta(n^2)\) 个 \([0,m-1]\) 内均匀随机的变量地期望最大值是 \(m-\dfrac{m}{n^2}\)。
考虑从大到小枚举这个最大的哈希值,设为 \(x\)。预处理前缀哈希值 \(h_i\),假如取到这个值的区间是 \([l,r]\),那么 \(h_r=b^{r-l+1}h_l+x\)。整理一下可以得 \(b^{-r}(h_r-x)=b^{-l+1}h_{l-1}\)。把右边插入一个哈希表,但注意要判断是否有 \(l\le r\)。
注意哈希表范围要开大一点。假如要哈希的整数的范围是 \([0,N]\),哈希表大小为 \(M\),那么期望一次插入、查询的时间复杂度为 \(O(\dfrac{N}{M})\)。
结论:\([0,1]\) 中均匀随机的 \(k\) 个实数,其中第 \(i\) 小的期望是 \(\dfrac{i}{k+1}\)。
Day3
A
数学题。
字符集大小仅为 \(3\),根据抽屉原理,单个字符的贡献至少为 \(\lceil \dfrac{n}{3} \rceil^2\)。
设一个循环节长度为 \(l\) 且循环 \(k\) 次的子序列是最优的,那么它一定要满足 \(k^2\lceil \dfrac{l}{3} \rceil^2<lk^2\),解得 \(l\le 6\)。
但这样合法的串仍然过多。对于一个子序列,我们枚举它的一个子序列,如果这个更小的子序列产生的贡献比原序列还多,直接舍掉原序列即可。
这样最后只会剩下 \(99\) 个串,能过。整个序列自动机即可。
B
题目:https://www.cnblogs.com/stoorz/p/14412034.html。
发现每种球只要有一个到达点 \(1\) 即可。
考虑网络流,由于操作有顺序,把每个点拆成 \(m\) 个,如果第 \(i\) 次操作 \(u,v\),那么在第 \(i\) 层上连边 \(u\leftrightarrow v\),流量限制为 \(1\)。
对于第 \((i-1)\) 层的点 \(u\) 和第 \(i\) 层的对应点 \(u'\),连边 \(u\to u'\),流量限制 \(a_u\)。
但这样边的个数达到了 \(O(nm)\) 级别,其中有许多无用点,把无用的点去掉即可,边数变成了 \(O(n+m)\)。
Day6
A
将链转化为环。
增加一个点 \((n+1)\),它与点 \(1\) 和点 \(n\) 相连,形成一个环。
于是原问题转化为放 \(m\) 个东西,并可以向左或向右走,在第一个没有标记的地方停下并添加标记,问点 \((n+1)\) 没有标记的方案数。
首先让每个机器人随便放,有 \((2n+2)^m\) 种方案。
考虑对二元组 \((S,x)\) 计数,其中 \(S\) 表示一种放点的状态,\(x\) 表示这种状态里未被标记的一个点。
每种状态内一定会有恰好 \(m\) 个点被标记,有 \((n-m+1)\) 个点未被标记。并且,我们只需要知道点 \((n+1)\) 没被标记的方案,点都是相同的,于是方案就是 \((2n+2)^m(n-m+1)(n+1)^{-1}\)。
C
\(n,m,\sum k\le 10^5\),考虑用 bitset 搞这个东西。
设 \(V\) 是值域,与 \(n\) 同阶。
对原序列分 \(\omega\) 块,每块存一个大小为 \(V\) 的 bitset,表示是否出现过这个数。
可以发现 bitset 的或运算满足幂等律,可以用 Sparse Table 存。设 \(\text{st}_{i,j}\) 为第 \([i,i+2^j)\) 块的 bitset。查询时直接取出来即可,时间复杂度 \(O(\dfrac{n}{\omega})\)。预处理的时间复杂度和空间复杂度是 \(O(\omega \log \omega\times \dfrac{n}{\omega})=O(n \log \omega)\)。
对于零散块,暴力查询,最多有 \(O(\dfrac{n}{\omega})\) 个位置,时间复杂度 \(O(\dfrac{n}{\omega})\)。
Day7
CF516E
势能分析。
\(\dots\dots\)
AGC023E
首先算满足条件的排列个数 \(S\)。只有 \(A_i=n\) 的位置可以填 \(n\),\(A_i\ge n-1\) 的位置可以填 \(n-1\)。于是设 \(c_i\) 为 \(A_k\ge i\) 的 \(k\) 个数,那么 \(S=\prod \limits_{i=1}^n (c_i-n+i)\)。
假如某个 \(c_i\) 满足 \(c_i-n+i=0\),那么 \(S=0\),特判掉。
现在一种暴力做法就是枚举 \(i,j\) 满足 \(i<j\),求出 \(P_i>P_j\) 的排列 \(P\) 个数。分类讨论:
- 假如 \(A_i=A_j\):个数为 \(\frac{S}{2}\)。
- 假如 \(A_i<A_j\):由于 \(P_i\) 一定小于等于 \(A_i\) 所以可以把 \(A_j\) 变成 \(A_i\) 并计算合法排列数 \(S'\),个数即为 \(\frac{S'}{2}\)。
- 假如 \(A_i>A_j\):按照 \(A_i<A_j\) 的方法做即可。
记前缀积 \(f_i=\prod \limits_{j\le i} c_j\),\(g_i=\prod\limits_{j\le i}(c_j-1)\)。那么假如令 \(A_j\gets A_i\),就可以用 \(f,g\) 表示出 \(S'\)。
枚举 \(i\),用线段树维护。
\(\dots\dots\)
CF555E
先 Tarjan 得出所有 e-DCC,将它们连成有向的强连通分量,这样其中任意两个点之间都连通。并将原图缩成一棵树,假如在这棵树上有 \(s\to t\),那么 \(s\to \operatorname{LCA}(s,t)\) 之间的边向上,\(\operatorname{LCA}(s,t)\to t\) 之间的边向下。
用树上差分判断是否合法即可。
ARC091F
设 \(SG_k(n)\) 表示 \(n\) 个石子,参数为 \(k\) 的 SG 函数。
找一下规律,可以发现先手必胜和先手必败是交替的。
\(SG_k(n)=\begin{cases} \dfrac{n}{k} & n \bmod k=0\\ SG_k(n-\lfloor \dfrac{n}{k}\rfloor)& \text{otherwise} \end{cases}\)
但这样递推可能会 TLE。注意到有时候 \(\lfloor \dfrac{n}{k}\rfloor\) 是不变的,这时候直接算出它什么时候会改变或者满足 \(n\bmod k=0\)。
时间复杂度:
\(\dots \dots\)
CF578F
\(\dots\dots\)
AGC035E
对于每个 \(x\) 满足 \(1\le x\le N\),连边 \(x\to x-2,x\to x+k\)。
然后对于 \(k\) 的奇偶分类讨论。
\(\dots\dots\)
CF575A
显然 \([f_{i},f_{i+1}]=\begin{bmatrix}0 & s_{i-1}\\ 1 & s_i \end{bmatrix}[f_i-1,f_i]\)。
记 \(A(i,j)=\begin{bmatrix}0 & i\\ 1 & j \end{bmatrix}\),答案就是 \([0,1]\times A(s_0,s_1)\times\dots\times A(f_{k-1},f_k)\)。
预处理出 \(A(s_0,s_1)\times\dots\times A(s_{n-2},s_{n-1})\)。
但这样会有一些特殊点,考虑线段树维护矩阵的乘积。
对于没有特殊点的段矩阵快速幂,有特殊点的乘一下。
用线段树,单点乘,全局查询积。
AGC039E
CF526F
Day8
CF547D
对于一组 \(x\) 或 \(y\) 相等的点,我们在它们之间连有向边,剩下的点不管。然后跑二分图染色即可。
为啥它是二分图?
FJOI2013 圆形游戏
先扫描线一遍求出圆之间的包含关系。于是转化成了树上删边游戏。
Day9
A
推一下 \(k\) 阶等差数列的式子,假如询问是 \([l,r]\),那么第 \(i\) 个位置对答案的贡献就是 \(\dbinom{r-i+k-1}{k-1}\)。所以它是一个关于 \(r\) 的 \(k\) 次多项式,用树状数组维护每个位置的多项式系数即可。
对于一次单点加操作,实际上是对它所在的树状数组上的区间对应的多项式,每项都乘上 \(\dfrac{a_i+x}{a_i}\)。
时间复杂度 \(O(nk\log n)\)。