CF *3200
1. CF573E Bear and Bowling
https://www.luogu.com.cn/problem/CF573E。
data structures, greedy。
题意:给定序列 \(a\),求一个 \(a\) 的子序列 \(b\) 使得 \(\sum_{i=1}^k ib_i\) 最大。
\(n\leq 10^5\)。
本题满足决策包容性,即:
- 可以贪心地选择使答案最大的数加入子序列中。
- 设 dp,\(f_{i,j}\) 表示前 \(i\) 个数选 \(j\) 个,那么 \(f_{i-1}\to f_i\) 一定是一段前缀 \(j\) 不选,一段后缀选。且 \(\dfrac{f_{i,j}-f_{i,j-1}}j\) 单调递减。
证明:归纳。首先有 \(\dfrac{f_{i-1,j}-f_{i-1,j-1}}j\) 单调递减,然后推出 \(f_{i-1}\to f_i\) 一定是一段前缀 \(j\) 不选,然后推出 \(\dfrac{f_{i,j}-f_{i,j-1}}j\) 单调递减。
这两个结论应该是等价的,且都可以继续优化。
第二个结论的优化方式是:找到第一个 \(\leq a_i\) 的 \(\dfrac{f_{i,j}-f_{i,j-1}}j\) 然后在差分数组 \(j\) 处插入 \(a_i*j\),后面都 \(+a_i\),平衡树维护。代码写的是直接分块。
https://codeforces.com/contest/573/submission/337949211。
2. CF1037H Security
data structures, string suffix structures。
https://www.luogu.com.cn/problem/CF1037H。
题意:给定串 \(S\),多次询问每次给定串 \(T\),求 \(S[L,R]\) 的子串内最小的一个字典序 \(>T\) 的子串。
\(|S|\leq 10^5,q,\sum |T|\leq 2\times 10^5\)。
核心做法是:枚举 \(T\) 前缀,找是否能够完全匹配 \(S[L,R]\) 内的一个子串,且 \(S\) 子串中后面一个字符比 \(T\) 的大。
SAM
建 \(S\) 的 SAM,在上面跳 \(T\),相当于求一个节点的子结点 endpos 集合与 \([L+len,R]\) 的交集,线段树合并维护 endpos 集合。
SA
对所有串拼起来建 SA,枚举 \(T\) 前缀找对应 \(sa\) 区间,即求区间内 \(sa_i\in[L,R-len]\) 的最小 \(i\)。
AC 自动机
AC 自动机可以做!发现对于 \(T\),可行答案只有 \(O(26|T|)\) 种,且建出来的 trie 也只有这么大。把所有 trie 合并后建 AC 自动机,然后在上面跑 \(S\) 即可。卡空间。
3. CF643G Choosing Ads
data structures。
https://www.luogu.com.cn/problem/CF643G。
题意:给定序列 \(a\),常数 \(p\in[20,100]\),多次操作,每次区间推平或找一个大小 \(\leq \lfloor\dfrac{100}p\rfloor\) 的集合使得询问区间内所有出现次数 \(\geq \lceil\dfrac {p(r-l+1)}{100}\rceil\) 的数都在这个集合中。
\(n\leq 1.5\times 10^5,p\in[20,100]\)。
正解:摩尔投票
令 \(k=\lfloor \dfrac{100}p\rfloor\),则每次删除 \(k+1\) 个不同的数,最后留下的数就是答案。使用线段树维护这个结构的集合合并即可。可以证明死掉的数都不满足题意,而活着的数只有 \(k\) 个,全部输出就可以,由于题目的特性不需要判断。
随机化
我们在序列中随机 \(B\) 个位置,然后查询这些位置上的数是否满足条件。问题变为维护区间推平和区间查询某颜色个数。考虑维护连续段,并且对于一个断点 \(a_i,a_{i+1},a_i\neq a_{i+1}\),在线段树 \(a_i\) 的位置 \(i+1\) 插入 \(1\);线段树 \(a_{i+1}\) 的位置 \(i+1\) 上插入 \(-1\),然后区间求和就可以维护查询。复杂度 \(O(nB\log n)\),\(B=80\) 即可,需要卡常。
https://codeforces.com/contest/643/submission/338022586。
4. CF1017G The Tree
data structures。
https://www.luogu.com.cn/problem/CF1017G。
题意:树上所有点均为白色,三种操作:1. 如果结点 \(v\) 是白色的,将其标记为黑色;否则,对 \(v\) 的所有直接儿子执行此操作。2. 将以 \(v\) 为根的子树中的所有结点(包括 \(v\) 本身)都标记为白色。3. 查询 \(v\) 颜色。
\(n,q\leq 10^5\)。
可以使用赋点权的方式刻画这个操作。
每个点初始点权为 \(-1\),表示它要吸收从上面来的一单位黑色;1 操作就是单点 \(+1\),表示这个点向下扩散了一单位黑色;2 操作就是将点权减去 \(query(v)+1\),表示它吸收了所有往下扩散的黑色,然后将子树覆盖为 \(-1\);3 操作就是查询这个点的根链有没有一个后缀和 \(\geq 0\)。
难点在于想到这个刻画方式,实际上是很形象的。
5. CF1810G The Maximum Prefix
dp。
https://www.luogu.com.cn/problem/CF1810G。
题意:长度为 \(n\) 的序列 \(a\),\(a_i\) 项有 \(p_i\) 的概率为 \(1\) 否则为 \(-1\)。一个序列的权值定义为:设它的最大前缀和为 \(S\),权值就为 \(h_S\)。对于 \(k\in[1,n]\) 求长度为 \(k\) 的序列 \(a\) 的期望权值。
\(n\leq 5000\)。
最大前缀和正着求需要记录 \(premax,nowsum\),但是倒着求不需要,此时若 \(a_i=1\),那么相当于 \((i,n]\) 的所有位置前缀和都 \(+1\),反之 \(-1\),所以只需要记录一个 \(nowmax\) 即可。每次要么变为 \(nowmax+1\) 要么变为 \(\max(0,nowmax-1)\)。
然后就可以写出 dp:
- 初值 \(f_{k,0}=1\);
- 转移 \(f_{i-1,j+1}\leftarrow f_{i,j}p_i,f_{i-1,\max(0,j-1)}\leftarrow f_{i,j}(1-p_i)\);
- 答案 \(\sum f_{0,i}h_i\)。
对于每个 \(k\) 都要 \(O(n^2)\) 转移,不能接受。所以考虑转置,变为了:
- 初值 \(f_{0,i}=h_i\);
- 转移 \(f_{i,j}=f_{i-1,j+1}p_i + f_{i-1,\max(0,j-1)}(1-p_i)\);
- 答案 \(f_{k,0}\)。
https://codeforces.com/contest/1810/submission/338154369。
6. CF585F Digits of Number Pi
dp, implementation, strings。
https://www.luogu.com.cn/problem/CF585F。
题意:求 \([x,y]\) 内正整数数量,满足这个正整数有一个 \(\geq len\) 的子串是 \(S\) 的子串。
\(|S|\leq 1000, x,y\leq 10^{50}\)。
直接 ACAM+ 数位 dp 即可。
7. CF538H Summer Dichotomy
2-sat, data structures, dfs and similar, greedy。
https://www.luogu.com.cn/problem/CF538H。
题意:有 \(T\) 个学生以及 \(n\) 个老师,现在要将至少 \(t\) 个学生分为两个组(其他学生不管),然后每个老师分到其中一个组,每个老师有要求:教的学生数量位于 \([l_i,r_i]\) 间,以及有 \(m\) 对老师不能分到一个组。求构造合法方案。
\(n,m\leq 10^5\)。
扫描线 \(O(n\log n)\)
将老师的 \(m\) 对关系建图,然后如果不是二分图无解,是二分图,每个连通块会得到两个区间 \([l_1,r_1],[l_2,r_2]\),表示两个组内的学生数量需要一个 \(\in [l_1,r_1]\),一个 \(\in[l_2,r_2]\),将对应条件画到平面直角坐标系上就可以扫描线扫过去了。
\(O(n+m)\)
如果不考虑 \([t,T]\) 和 \(m\) 的限制,设两组内学生数为 \(n_1,n_2\),有性质:
若存在解,则 \(n_1=\max l_i,n_2=\min r_i\) 为一组解。
若区间两两有交,则 \(n_1\leq n_2\),那么 \([n_1,n_2]\) 中任意一个点都能覆盖所有区间;否则,存在两个区间,一个右端点 \(n_2\),一个左端点 \(n_1\),那么 \((n_2,n_1)\) 内不能选择任何点,否则上述两个区间总会有一个不满足。
因此能够得到 \([t,T]\) 限制时的做法:若 \(n_1+n_2<t\),加 \(n_1\);否则减 \(n_2\)。确定这两个数后 check 是简单的。
8. CF1621G Weighted Increasing Subsequences
data structures, dp, math。
https://www.luogu.com.cn/problem/CF1621G。
题意:给定序列 \(a\)。对于序列 \(a\) 的长度为 \(k\) 的严格递增子序列 \(a_{i_1}, a_{i_2}, \ldots, a_{i_k}\),其权值定义为满足以下条件的 \(1 \leq j \leq k\) 的个数:存在下标 \(i_k < x \leq n\),且 \(a_x > a_{i_j}\)。求 \(a\) 的所有严格递增子序列的权值和。
\(n\leq 2\times 10^5\)。
容易发现,对于任意一个严格递增子序列,能够取到的最优的 \(a_x\) 一定是这个序列右侧的第一个非严格后缀最大值,将这些非严格后缀最大值位置标记出来。
显然,对于没有标记的位置,以这些位置结束的严格递增子序列一定能找到一个 \(a_x\) 使得所有下标都有贡献,直接设 \(f,g\) 表示方案数/权值和,树状数组优化 dp 即可。
对于有标记的位置,这些序列可能有一个后缀没贡献。但是可以发现,设这个标记位置为 \(i\),下一个标记位置为 \(j\),那么除掉 \(a_i\) 只会有权值 \(\in [a_j,a_i)\) 这一段位置的数没有贡献。
设后缀最大值分别为 \(b_0=0,b_1,b_2,...,b_p\),对序列中所有元素按照值域 \(\in[b_i,b_{i+1})\) 分为若干段,那么以 \(a_i=b_v\) 结尾的严格递增子序列,值 \(\in[b_0,b_{v-1})\) 内的数是有贡献的,\(\in[b_{v-1},b_v)\) 以及 \(a_i\) 是没有贡献的。于是设 \(h_i\) 表示以 \(i\) 结尾,且与 \(a_i\) 在同一值域组的那些元素不计算贡献的权值和,不需要方案数是因为后面的元素都没有贡献。\(h\) 的转移同样可以树状数组优化。
https://codeforces.com/problemset/submission/1621/338223594。
9. CF786E ALT
data structures, flows, graphs, trees。
https://www.luogu.com.cn/problem/CF786E。
题意:一棵树上 \(m\) 条路径,每条路径对应一个居民,每条边对应一个守卫。分糖果,每个居民和守卫都能分到 0/1 个糖果,要求每个居民有糖果,或者他对应的路径上所有守卫都有糖果。求最少糖果数,以及方案。
\(n,m\leq 20000\)。
树剖线段树优化建图跑最小割即可。
https://codeforces.com/contest/786/submission/338306542。
10. CF1034E Little C Loves 3 III
bitmasks, dp, math。
https://www.luogu.com.cn/problem/CF1034E。
题意:求长度 \(2^n\) 的数组 \(a,b\) 子集卷积 \(\bmod 4\)。
\(n\leq 21\),空间 62MB。
直接子集卷积显然不行,需要一次卷积的做法。
考虑构造 \(A_i=a_i\times 4^{\operatorname{popcount}(i)}\),\(B_i\) 同理,然后对 \(A,B\) 进行或卷积得到 \(C\),答案就是 \(\dfrac {C_i}{\operatorname{popcount}(i)}\bmod 4\)。证明显然。
https://codeforces.com/contest/1034/submission/338608609。
11. CF1656H Equal LCM Subsets
data structures, math, number theory。
https://www.luogu.com.cn/problem/CF1656H。
题意:给定两个集合,求各自的一个子集,使得两个子集 \(\operatorname{lcm}\) 相等。
\(n,m\leq 1000,V\leq 4\times 10^{36}\),10s。
数据范围限制我们不能做任何 \(\operatorname{lcm}\) 和乘法操作。
考虑目前选择全集,什么情况一个数必须删掉:这个数拥有一个对面的所有数都没有的质因子,可以通过 \(\gcd\) 来构造出这个条件:
用 \(n+m\) 棵线段树维护这个式子即可。复杂度 \(O((n+m)^2(\log n+\log m+\log w))\)。
https://codeforces.com/contest/1656/submission/338658187。
12. CF611H New Year and Forgotten Tree
constructive algorithms, flows, graphs。
https://www.luogu.com.cn/problem/CF611H。
题意:给你一棵树,但是每条边只告诉你两端点十进制位数,构造一组合法方案或者无解。
\(n\leq 2\times 10^5\)。
第一想法:建 \(\log_{10} n\) 个点,然后点 \(i,j\) 连了 \(k\) 条边相当于合并 \(i\) 内 \(p\) 个连通块, \(j\) 内 \(k-p-1\) 个连通块,然后跑匹配即可。
这个是不对的,因为无法保证几个集合之间不形成环。
正确做法还需一步:枚举每个集合之间一个关键点,然后其他点可以连向某个关键点(不一定是同一集合内部的关键点),然后 prufer 序列枚举这些集合内部树形结构,,,
13. CF650E Clockwork Bomb
data structures, dfs and similar, dsu, greedy, trees。
https://www.luogu.com.cn/problem/CF650E。
题意:给你两棵树,每次可以在第一棵树上删一条边、加一条边,要求过程中仍然是树,然后变成第二棵树。求最小操作数和构造方案。
\(n\leq 5\times 10^5\)。
首先方案数肯定是 \(n-1\) 减去两棵树边交集大小。
方向 1(做不下去)
考虑以第二棵树为主树,然后从叶子开始向上考虑。若第二棵树上 \(x\)->父亲 \(y\) 的边在第一棵树上没有,那么:
- 断第一棵数上 \(x\) 到父亲 \(z\) 的边,然后连 \(x\to y\),可能不可行(此时 \(x\to y\) 也有边)
- 但是此时第二棵树上 \(x\to z\) 的路径上一定有一条边,两端点在第一棵树断掉 \(x\to z\) 时在第一棵树上不连通。加这一条边即可。
难以优化到更好的复杂度。
方向 2
考虑以第一棵树为主树,然后从叶子开始向上考虑。
显然两棵树里面都有的边不用动,可以用并查集把这条边的两个端点缩在一起,代表元素是第二棵树上最浅的那个元素。
因为每次操作完之后仍要是一棵树,所以我们可以对于每一个叶子节点,把在第一棵树上与它父亲相连的边断开,再连上第二棵树上的父亲,这样就不会形成环。
https://codeforces.com/contest/650/submission/339704045。
14. CF1149E Election Promises
games, graphs。
https://www.luogu.com.cn/problem/CF1149E。
题意:给你一张 DAG,每个点有点权。两个人交替操作,每个人选择一个点使它权值减去一个正整数(要求减完依旧 \(\geq 0\)),并且将它的出边连向的点点权改为任意非负整数。若图上所有点权均为 \(0\) 则输。求最后谁会赢。
\(n,m\leq 2\times 10^5\)。
CF1451F Nullify The Matrix
题意:DAG 换成矩阵,出边连向的点换成一条到 \((n,m)\) 的四联通路径。
考虑 \(1\times 2\) 的矩阵,点权分别为 \(a,b\),然后显然后者的 SG 值是 \(b\),但前者的 SG 值是什么?会发现是 \(a+b\times \omega\)。然后整个局面的 SG 值就是 \(\sum_k \omega^k \operatorname{xor}_{i+j=k+2} a_{i,j}\)。那么定义 SG \(=0\) 就是每一项 \(\omega\) 的系数为 \(0\),就意味着每一条与反对角线平行的斜线异或值为 \(0\)。
也可以将 SG 值写成多项式的系数表达式,然后构造出一个非 \(0\) 能到 \(0\);\(0\) 不能到 \(0\) 的集合划分就行。
本题
直接推有点太麻烦了,考虑构造出一个非 \(0\) 能到 \(0\);\(0\) 不能到 \(0\) 的集合划分就行。
将所有出度为 \(0\) 的点的标号设为 \(0\)。然后拓扑排序,每个点的标号是它的后继节点编号的 \(\operatorname{mex}\) 即可。
证明是简单的。
https://codeforces.com/contest/1149/submission/339819181。
15. CF464E The Classic Problem
data structures, graphs, shortest paths。
https://www.luogu.com.cn/problem/CF464E。
最短路,但是每条边权值 \(2^{w_i}\)。
\(n,m,w_i\leq 10^5\)。
典 题。
主席树维护 dis,支持二分用来 \(+1\),维护哈希值用来比大小。
16. CF1119H Triple
fft(并非), math。
https://www.luogu.com.cn/problem/CF1119H
题意:你收到了生日礼物——\(n\) 个整数三元组!第 \(i\) 个三元组为 \(\lbrace a_{i}, b_{i}, c_{i} \rbrace\)。所有数字都大于等于 \(0\),且严格小于 \(2^{k}\),其中 \(k\) 是一个固定的整数。有一天,你玩三元组玩累了,于是你想出了三个新整数 \(x\)、\(y\)、\(z\),然后构造了 \(n\) 个数组。第 \(i\) 个数组由 \(a_i\) 重复 \(x\) 次、\(b_i\) 重复 \(y\) 次、\(c_i\) 重复 \(z\) 次组成。因此,每个数组的长度为 \(x + y + z\)。你想从每个数组中恰好选出一个整数,使得它们的异或和(按位异或)等于 \(t\)。请输出对于每个 \(t\) 从 \(0\) 到 \(2^{k} - 1\),恰好选出一个数使异或和为 \(t\) 的方案数,结果对 \(998244353\) 取模。
\(n\leq 10^5,k\leq 17\)。
设 \(F_i[j]=x[j=a_i]+y[j=b_i]+z[j=c_i]\),那么答案可以写作 \(F_1*F_2*F_3*...*F_n\)。
考虑 FWT。设 \(G_i[j]=\sum_{i=1}^n\operatorname{FWT(F_i)}[j]\),则答案为 \(\operatorname{IFWT}(G_i)\)。
问题变为如何求 \(G_i\)。
FWT 有个经典结论是,\(\operatorname{FWT}(F)[i]=\sum_j F_j(-1)^{i\operatorname{AND}j}\)。
所以,\(\operatorname{FWT}(F_i)[j]=(-1)^{|j\operatorname{AND}a_i|}x+(-1)^{|j\operatorname{AND}b_i|}y+(-1)^{|j\operatorname{AND}c_i|}z\),只有 \(\pm x\pm y\pm z\) 八种取值。
这里是一个经典 trick:如果 FWT 的值域很小而定义域很大,考虑直接把每个位置每个值出现多少次算出来。
假设我们要算第 \(j\) 位的 \(+x+y+z\) 出现了几次,设其为 \(p_j\),则:
如果要改成 \(-x+y-z\) 之类的,需要将对应项分子的 \(+1\) 变为 \(-1\),然后全局再乘一个 \(-1\)。
即要求类似于 \(\sum_{i=1}^n(-1)^{|j\operatorname{AND} a_i|}(-1)^{|j\operatorname{AND} b_i|}\) 之类的东西。
对于只有一项是好求的,我们设 \(T_i[j]=[j=a_i]\),那么 \(\operatorname{FWT}(T_i)[j]=(-1)^{|j\operatorname{AND}a_i|}\)。然后有 \(\operatorname{FWT}(A+B)=\operatorname{FWT}(A)+\operatorname{FWT}(B)\),所以我们只用计算 \(\operatorname{FWT(\sum T)}\) 即可。这个是好算的,因为 \(T_i\) 只有一项有值。
对于有两项、三项的怎么做?观察到,\((-1)^{|j\operatorname{AND}a_i|}(-1)^{|j\operatorname{AND} b_i|}=(-1)^{|j\operatorname{AND}(a_i\operatorname{XOR}b_i)|}\)!!!那么设 \(T_i[j]=[j=a_i\operatorname{XOR}b_i]\) 即可。三项同理。
一项一项地往前代入即可。

浙公网安备 33010602011771号