CF 刷题笔记 贰
第一篇写不开了,再开一篇。
1558D
难度:2600。
仙品。注意到题目相当于告诉我们 \(m\) 组大小关系,让我们求可能的排列个数。如果我们知道小于号的个数 \(c\),那么使用插板法可得答案就是 \(C_{2n-c-1}^n\),于是问题转化为求 \(c\)。我们维护一个集合 \(S\),存储所有的前面是小于号的数,答案就是 \(\# S\),于是考虑一个条件 \(a_i<a_j\) 时,如果 \(j\) 不在 \(S\) 中,也就是说 \(a_j\) 前面是 \(\le\),那就把 \(j+1\) 插进去,并且把 \(S\) 中所有比 \(j\) 大的数加一。我们考虑如何用一个 DS 维护集合 \(S\),也就是说这个 DS 需要维护插入和区间加,于是想到平衡树。code
420D
难度:2200,洛谷蓝
反着考虑就完了。code
2013E
难度:2200
首先前缀 \(\gcd\) 是单调不升的,我们尽量在前面下降,然后降到 \(\gcd(a_1,\dots,a_n)\),然后直接停下,这样贪心就是对的,并且复杂度是 \(O(n\log n)\) 的,因为每一次下降最少降为原来的 \(\frac{1}{2}\),所以 \(n\log n\) 一般情况下跑不满,这样就过了。code
1301F
难度:2600
很自然地想到把颜色相同的点缩起来跑 Floyd,预处理原来的点不通过传送到缩起来后的点的距离,然后每次询问枚举第一次和最后一次在那个颜色传送,时间复杂度 \(O(nmk+qk^2)\),但是 \(qk^2\) 太大了。于是考虑直接搞点可以经过传送到某个颜色的距离,这个对每个颜色跑一遍 bfs 就行了。记 \(d(i,x,y)\) 表示点 \((x,y)\) 到颜色为 \(i\) 的点们的距离,答案就是起点与终点间曼哈顿距离与
取 \(\min\) 的结果。时间复杂度 \(O(k(nm+q))\),稳稳过。code
2078D
difficulty:1800
STO Wei_Han ORZ
从前往后看问题,发现问题具有后效性,没法 DP,折半也是不行的因为我们并不能很好地合并前后两端的答案,于是正难则反,考虑反着做,发现这样就没有后效性,只用考虑后几位的答案就行了。
再求值之前,我们先做一些操作。我们将左边的门编号为 \(0\),右边的门编号为 \(1\),我们设 \(a_{i,o}\) 表示第 \(i\) 关编号为 \(o\) 的门做乘法操作的倍数,如果是加法门,就令 \(a_{i,o}=1\),然后另计 \(b_{i,o}\) 表示加上的数。。我们设 \(f_{i,o}\) 表示考虑到第 \(i\) 个关卡左/右边的门对前面的决策产生的贡献。易知对于当前一个门,加法门所产生的贡献并不会对前面造成什么影响,而对于每个门产生的贡献,把这些贡献全部放到能产生更大贡献的那一边要比留一些在更劣的一边优,于是我们得到递推式
并且如果当前出现加法门,则使
并且在最后给答案加上 \(f_{1,0}+f_{1,1}\),时间复杂度 \(O(nT)\),好奇为什么 \(n\) 要放这么小。code
2092E
difficulty:2100
hint:对于有偶数个相邻块的块,它自己啥颜色对答案有关吗?
没有关!所以只用考虑边边上的就行了。然后就做完了。code
1716D
difficulty: 2000
定义 \(f_{i,j}\) 表示第 \(i\) 个点被地第 \(j\) 次走到的方案数。列转移是容易的,但是转移复杂度太高。
考虑 \(j\) 这一位,发现它并不是 \(O(n)\) 的,而是 \(O(\sqrt n)\) 的,所以可以暂且不管这一维。然后就可以前缀和优化直接做了。代码我没写。
2091G
difficulty: 2300
定义 \(f_{i,j}\) 表示走 \(j\) 步能否到达 \(i\),转移容易列出,但 \(i\) 的规模太大了,一些特殊的性质。发现当 \(s>k^2\) 的时候,两次一定可以,于是 \(i\) 的规模就变成了 \(10^6\),但这还是过不了,并且发现想不动了,于是挂个 bitset 就行了。
OI 中可以使用的动态 bitset: https://codeforces.com/blog/entry/129454
1091E
difficulty:2400
抽象没边了。
hint:链接最有效的一集。
Erdős–Gallai定理:对于一个序列 \(d_1,d_2,\dots,d_n\),它可以成为一个简单无向图的度数的序列:等价于
\(2|(\sum d)\);
\(\forall k\in \{1,2,\dots,n\},\sum_{i=1}^k d_i\leq k(k-1)+\sum_{i=k+1}^n\min(d_i,k)\)。
对于 1,考虑每条边的贡献即可;对于 2,右边前一个式子是内部的,第二个式子是内部和外部的。
利用这个定理的朴素做法就是枚举 \(d_{n+1}\),判断是否可行,时间复杂度 \(O(n^2)\)。
尝试寻找性质,观察阳历发现,如果 \(d_{n+1}\) 是 \(x\) 或 \(y\) 时满足条件,那么对于所有 \(x<z<y\) 且 \(z\) 与 \(x,y\) 奇偶性相同,\(d_{n+1}=z\) 也是可以的。
于是将原序列排序,然后二分上下界。check 的时候考虑把当前值插入序列并保证序列单调性的位置就行了。时间复杂度 \(O(n\log n)\)。code
1149D
difficulty: 3000
称边权为 \(a\) 的边为轻边,其余称为重边。我们发现去掉重边之后剩下的可以构成几坨连通块,并且如果一条路径在最小生成树上,那么它只会进出一个连通块最多一次。于是在连通块上 dp。设 \(f_{S,u}\) 表示当前走过的连通块的集合为 \(S\),当前走到点 \(u\) 的最短距离。由于 \(f_{S,u}\) 可以转移到 \(f_{S,v}\) 意味着反过来也是可以的,所以需要用最短路的方式 dp,时间复杂度 \(O(2^nm\log(2^nm))\),考虑优化。然后注意到对于 \(siz\leq 3\) 的连通块不需要考虑,因为走内部边总一进一出快,于是时间复杂度 \(O(2^{n/4}m\log(2^{n/4}m))\)。code
1764H
difficulty: 3400
倒着做,考虑维护 \(t\) 表示每个位置上的数最多能活多久,然后每次操作相当于对 \((l\dots r]\) 上的点区间覆盖,对 \(l\) 上的点,\(t_l\leftarrow \max_{x=l+1}^rt_x\),其连续段个数综合是 \(O(n)\) 的,于是可以用 set 维护连续段,时间复杂度 \(O(n\log n)\),同时用树状数组数点,当前的答案就是 \(t_i>x+k-1\) 的位置。code

浙公网安备 33010602011771号