【笔记】CF 选做
【笔记】CF 选做
CF505E
- 给定 \(n\) 个数 \(h_{1 \dots n}\)。
- 你需要进行 \(m\) 轮操作,每轮操作为 \(k\) 次修改,每次修改可以选择一个数 \(h_i\) 修改为 \(\max(h_i - p, 0)\)。
- 每轮操作后每个 \(h_i\) 将会被修改为 \(h_i + a_i\)。
- 你需要最小化最终 \(h_{1 \dots n}\) 中的最大值。
- \(n \le 10^5\),\(m \le 5 \times 10^3\),\(k \le 10\)。
逆向思考。操作中有对 \(0\) 取 \(\max\) 操作不好处理。我们二分答案 \(mid\),将 \(h\) 的结束值都设为 \(mid\),然后倒推。对 \(0\) 取 \(\max\) 的操作变成限制,即倒推的过程中不能出现 \(<0\) 的数。用堆维护贪心即可。
CF512D
- 给定一张 \(n\) 个点 \(m\) 条边的无向图。
- 一个点只有当与它直接相连的点中最多只有一个点未被选择过时才可被选择。
- 询问对于每个 \(k \in [0,n]\),有序选择 \(k\) 个点的方案数。
- \(n \le 100\),\(m \le \frac{n(n-1)}2\),答案对 \(10^9+9\) 取模。
我们把选择一个点看成删去一个点,那么我们求得就是类似拓扑序的东西。图中的环无法被删去,我们先将图中的环预处理掉。
现在图只剩下有根树和无根树。前者方案可以一遍树形 DP求得。后者我们可以以每个点为根求一次树形 DP,发现一个 \(k\) 个点的方案恰好被计算了 \(size- k\) 次。
我们也可以进行换根 DP。在将根移动时,钦定原根所在子树必须被选满。这样也可以做到不重不漏。
CF516D
- 给定一棵 \(n\) 个点的树,边有边权。
- 定义 \(f_x = \max_{i=1}^n \text{dist}(x,i)\)。
- \(q\) 次询问最大的满足 \(\max_{x \in s} f_x - \min_{x \in s} f_x \le l\) 的连通块 \(s\) 包含的点数。
- \(n \le 10^5\),\(q \le 50\)。
先求出直径,然后求出 \(f\)。
观察一下,我们发现最小的 \(f\) 一定在树的中心位置,然后向外 \(f\) 逐渐增大。
由于限制是 \(\max - \min\),很自然想到双指针,同时用并查集维护连通块大小即可。
CF516E
有 \(n\) 个男生 \(m\) 个女生,编号分别为 \(0 \sim n - 1\) 和 \(0 \sim m - 1\)。
有 \(b\) 个男生和 \(g\) 个女生是快乐的,其他人是不快乐的。
在第 \(i\) 天,编号为 \(i \bmod n\) 的男生和编号为 \(i \bmod m\) 的女生会一起玩。如果他们俩中有一个人是快乐的,则另一个人也会变快乐。
求至少要多少天所有人都会变快乐,或者判断不可能所有人都变快乐。\(n,m \le 10^9\),\(b,g \le 10^5\)。
数论/思维题。
记男左女右。左指针以 \(n\) 为周期,右边以 \(m\) 为周期,循环节就是 \(\operatorname{lcm}(n,m)\),左 \(i\) 和右 \(j\) 可能见面当且仅当 \(i\equiv j \pmod {\gcd(n,m)}\)。
我们独立解决每组可能见面的人,问题转化为 \(n,m\) 互质。手算一下样例,如果左 \(i\) 感染了右 \(j\),那么右 \(j\) 会在 \(m\) 天后感染左 \((i + m)\bmod n\),所以如果以 \(m\) 为周期,\(i \to i + m\) 需要一个周期。而 \(n,m\) 互质,所以 \(i \to i + m\) 正好是一个环。我们模拟一下环上最短路即可。我们只保留最初从右边传染到左边的人作为关键点,否则复杂度过高。
具体实现比较复杂。我们用扩展欧几里得算法快速求出关键点在环上的位置,然后沿着环走两圈,或直接从最小的点走,关键点能松弛就松弛。从左到右也一样的做法。
CF521D
- 有 \(k\) 个正整数 \(a_{1\dots k}\)。
- 有 \(n\) 个操作,每个操作给定正整数 \(t, i, b\),有三种可能:
- 如果 \(t = 1\),这个操作是将 \(a_i\) 赋值为 \(b\);
- 如果 \(t = 2\),这个操作是将 \(a_i\) 加上 \(b\);
- 如果 \(t = 3\),这个操作是将 \(a_i\) 乘以 \(b\)。
- 你可以从 \(n\) 个操作中选择最多 \(m\) 个操作,并按照一定顺序执行。
- 你的目标是最大化 \(\prod_{i=1}^k a_i\) 的值。\(k,n \le 10^5\)。
等效转化。首先我们肯定按照 \(1\to 2\to 3\) 的顺序进行操作。而对于 \(3\) 操作,可以看成是全局操作,我们将所有 \(3\) 操作只保留权值放到一起。
对于 \(1\) 操作,对每个 \(a_i\) 只保留最大的,那么就可以看成进行一次加法操作。
现在我们只用考虑 \(2\) 操作。我们想办法把 \(2\) 操作变成 \(3\) 操作。事实上这是可行的,对于 \(b\) 操作肯定优先选大的,那么顺序就固定了。记录一下前面加的数,就转化为一次乘法 \(\times \dfrac{pre + b_i}{pre}\),最后所有乘法贪心选就行。
CF521E
- 给定一张 \(n\) 个点 \(m\) 条边的无向简单图。
- 问图中能否找到两个点,满足这两个点之间有至少三条完全不相交的简单路径。
- \(n,m \le 2 \times 10^5\),图不保证连通。
优先考虑转化为树来做。我们先生成 DFS 树,所有边变成树边和返祖边。讨论几种情况,发现有三条不相交路径等价于存在两条对应树链相交的返祖边。这已经可以简单维护了。
CF526F
给定一个排列,求有多少区间满足排序后是一段连续的数。\(n\le 3\times 10^5\)。
条件转化一下,就是有多少区间 \(\max - \min = r - l\)。
我们枚举右端点 \(r\),求有多少左端点是 \(\max - \min +\ l = r\),其中 \(\max,\min\) 是后缀最大值/最小值,我们用单调栈维护,同时用线段树维护每个 \(l\) 的值。
我们需要支持区间加,区间查询 \(=r\) 的数,本来这并不能用线段树维护,但是有性质 \(\max - \min + l \ge r\),所以我们用线段树维护区间最小值个数即为答案。
CF526G
给定一棵 \(n\) 个节点的无根树,每条边有边权。
有 \(q\) 次询问,每次询问给出 \(x,y\),你需要选择 \(y\) 条树上的路径,使这些路径形成一个包含 \(x\) 的连通块,且连通块中包含的边权和最大。
\(n, q \le 10^5\),强制在线。
妙妙题。第一步我们先贪心,选择的路径一定是叶子到叶子,否则可以继续延长答案不会变差。
先不考虑 \(x\) 的限制,那就是选出若干个叶子连出一棵虚树。其中我们一定会选出直径的一端,所以我们以直径的端点作为根结点,其余每选择一个叶子,都是覆盖叶子到根的路径。
这样转化为经典问题,求树上 \(k\) 条叶子到路径使得路径的交最大,直接长链剖分取最长的 \(k\) 个链。现在考虑 \(x\) 的限制,如果 \(x\) 不在最长的 \(k\) 个链中,我们就修改一条链把 \(x\) 所在链加进去。
CF527E
- 给定一张 \(n\) 个点 \(m\) 条边的连通无向图。
- 你需要加尽可能少的边,然后给所有边定向,使得每一个点的出入度都是偶数。
- 边可以是自环,也可以有重边。
- \(n \le 10^5\),\(m \le 2 \times 10^5\)。
每个点的出入度都是偶数,必要条件是每个点度数都是偶数。我们将奇点两两配对连边变成偶点。原图一定存在欧拉回路。即存在一个大环经过每条边。如果环长是偶数,我们将奇数边正向,偶数边逆向即可构造答案。否则我们加入一个自环将环长变成偶数。
CF536D
- 给定一张 \(n\) 个点 \(m\) 条边的可能有自环和重边的无向连通图,每条边都有一个非负边权。
- 小 X 和小 Y 在这张图上玩一个游戏,在游戏中,第 \(i\) 个城市有一个权值 \(p_i\)。
- 一开始,小 X 在城市 \(s\) 中,小 Y 在城市 \(t\) 中,两人各有一个得分,初始为 \(0\),小 X 为先手,然后轮流进行操作。
- 当轮到某一个人时,他必须选择一个非负整数 \(x\),以选定所有与他所在的城市的最短距离不超过 \(x\) 的还未被选定过的城市,他的得分将会加上这些城市的权值。
- 另外,每个人每次必须能够至少选定一个城市。
- 当没有人可以选择时,游戏结束,得分高者获胜。
- 现在请你计算出,在两人都使用最佳策略的情况下,谁会获胜(或者判断为平局)。
- \(n \le 2 \times 10^3\),\(m \le 10^5\),\(|p_i| \le 10^9\)。
转化为清晰的数学模型。先求出每个点到 \(s/t\) 的距离,即为 \((d_s,d_t)\),然后将点放到二维平面上。那么每次操作就是将 \(x\le c\) 或 \(y\le c\) 的点取出。每次至少取一个点。
由于两人都是最优策略,考虑倒推。每次放回 \(x\ge c\) 或 \(y\ge c\) 的点,这等价于将原来的 \((a,b)\) 点右上方的矩形扩展到 \((a,c)\) 或 \((c,b)\) 右上方的矩形。直接记状态 \(f_{a,b,0/1}\) 表示 \((a,b)\) 右上方,先/后手答案,枚举 \(c\) 转移可以做到 \(\mathcal{O}(N^3)\)。记录后缀最大值即可优化至 \(\mathcal{O}(N^2)\)。
CF538H
给定若干个区间 \([l_i,r_i]\),将区间分为两组,其中有些区间不能分在一组,使得存在 \((p,q)\) 满足 \(p\) 在第一组所有区间内,\(q\) 在第二组所有区间内,且 \(p+q\in[L,R]\)。
我们需要分两组,且一些不能同组,非常像二分图/2-SAT模型。但是直接做非常没有头绪,特别是 \(p+q\in [L,R]\) 的条件。
如果不考虑这个条件,我们可以先贪心求出一组可能的解 \(p = \max\{l_i\},q = \max\{r_i\}\)。
如果 \(p \le q\) 显然合法。
如果 \(p>q\),说明存在两个区间 \(l_i \le r_i < l_j \le r_j\),那么 \(p\) 减小就不满足 \(j\),\(q\) 增大就不满足 \(i\)。那么如果 \(p+q < L\),那么就只能增大 \(p\),如果 \(p+q >R\),就只能减小 \(q\)。
所以我们可以直接贪心求出最可能的 \((p,q)\),这组 \((p,q)\) 合法是存在解的充要条件。
我们把 \((p,q)\) 带入原区间就可以得到每个区间可以分在 \(1/2\) 组,限制条件可以直接二分图染色判断。
这题的核心在于贪心找到一个特定解使之代表所有可能的情况。类似与二分是将最优化问题转化为判定,这里是贪心将构造题通过最优化转化为判定。
Upd:2022/6/8
想到一个新思路。上面直接构造非常难想。
这样考虑。如果所有区间有交,那么就可以暂时忽略 \(p,q\) 条件。否则一定存在两个区间使得 \(r_i < l_j\),我们钦定 \(i\) 是第一组,\(j\) 是第二组,那么所以有 \(p \le r_i,q \ge l_j\),想要改变 \(p+q\) 的值,就只能修改其中一个。
CF547D
- 给定 \(n\) 个整点。
- 你要给每个点染成红色或蓝色。
- 要求同一水平线或垂直线上两种颜色的数量最多相差 \(1\)。
- \(n,x_i, y_i \le 2 \times 10^5\)。
行列模型。对于每个点 \((x,y)\),连无向边 \(x\leftrightarrow y\)。
问题等价于给每条边定向,使得每个点出入度的差 \(\le 1\)。首先任意图度数为奇数的点一定是偶数个。两两配对后,对每一对求出 \(s_i \to t_i\) 的路径,并定向。此时度数差 \(\le 1\)。剩下的子图每个点度数为偶数,求欧拉回路,对度数差没有影响。
CF547E
给定 \(n\) 个字符串 \(s_{1 \dots n}\)。
\(q\) 次询问 \(s_k\) 在 \(s_{l \dots r}\) 中出现了多少次。
\(n, \sum |s| \le 2 \times 10^5\),\(q \le 5 \times 10^5\)。
子串匹配,优先考虑 AC 自动机。对于 \(k\) 的询问,等价于在 fail 上 \(k\) 串对应结点的子树里求。我们考虑线段树合并维护每个点 \(s\) 区间的贡献。对询问直接单点查询即可。
CF555E
- 给定一张 \(n\) 个点 \(m\) 条边的无向图。
- 给定 \(q\) 组有向点对 \((s, t)\)。
- 询问是否存在使得所有 \(s\) 都能到达 \(t\) 的无向图中每条边的定向方案。
- \(n,m,q \le 2 \times 10^5\)。
边双缩点,对于 \(s,t\) 在一个边双中可以任意到达。缩完后形成一棵树,每次将 \(s\to t\) 的树边定向即可。
CF559E
有 \(n\) 条线段。
每条线段给定其中一端的位置及长度。
求所有线段覆盖的最大长度。
贪心 + DP。先将所有线段按端点排序。
为避免被多条线段覆盖的区间重复计算,我们需要记录当前覆盖的最右端点。所以我们定义状态 \(f_{i,j,0/1}\) 表示前 \(i\) 个端点,覆盖的最右端点是第 \(j\) 条线段向左/右。枚举 \(p,k\),转移 \(f_{p,k,0/1} \to f_{i,j,0/1}\),贪心的将 \([p+1,i - 1]\) 的线段全部向右。因为如果存在 \(t\in[p + 1, i - 1]\) 向左,可以转移 \(f_t \to f_i\)。
CF566C
给定一颗树,距离定义为边权和的 \(\frac{3}{2}\) 次方,求树的带权中心
如果我们距离的定义为边权和,显然我们可以指定一个点,然后一直调整到最优。
我们可以延续这个思想,我们从任意一个点开始,存在且恰好存在一条出边使得代价更小,我们一直沿着这条边走就行。
那么我们如何快速求出这条边呢,我们可以只向该方向走一个极小的值,那么该方向子树内为 \(\sum w_i (l_i - \Delta)^{\frac{3}{2}}\),其余的贡献为 \(\sum w_i(l_i+\Delta)^{\frac{3}{2}}\)。
现在令 \(\lim \Delta \to 0\),那么就是对函数 \(\sum w_i l_i^{\frac{3}{2}}\) 求导,所以我们要求的就是子树内 \(\sum \frac{3}{2}w_i\sqrt l_i\)。
由于根号的存在,每移动一次,所有的 \(\sqrt{l}\) 的变化无法快速计算,所以每次都需要 \(\mathcal{O}(N)\) 重新统计代价。不过有一个经典的 trick 就是直接点分治,每次只递归一半即可。复杂度和序列分治一样。
CF566E
有一棵 \(n\) 个点的树,你不知道这棵树的边是怎么连的。
你得到了 \(n\) 条关于每个点信息,每条信息记录了距离某一个点 \(\le 2\) 的所有点。
但你不知道每条信息具体是哪个点的。你需要构造一棵满足这些信息的树。\(n \le 10^3\)。
构造题。
观察一下。如果两个点距离为 \(3\),那么两点信息交集一定是两个点,且两点之间一定有边。这样我们就可以得到所有非叶结点形成的树。然后叶节点的信息就是它的兄弟集合。注意要考虑非叶节点 \(<3\) 的 corner case。
CF568E
给定一个长度为 \(n\) 的有 \(k\) 个空缺的序列。
你有 \(m\) 个数可以用于填补空缺。
要求最大化最长上升子序列的长度。\(n, m \le 10^5\),\(k \le 10^3\)。
首先问题不弱于 \(n \log n\) 的 LIS,考虑 LIS 的贪心做法。
进行一个关键转化,我们将 \(m\) 个数从大到小排序,原问题等价于在空缺插入这 \(m\) 个数。直接做是 \(mk\log\) 的,但是这 \(m\) 个数插入不用每次都二分,因为是有序的所以直接双指针即可。复杂度就是 \(\mathcal{O}((n+m)k+n\log n)\) 的。最后倒序还原序列即可。
CF571D
对于这类合并问题。我们可以建出合并树,问题就转化为子树上的问题,可以简单维护。
CF573E
- 给定一个长度为 \(n\) 的序列 \(a_{1\dots n}\)。
- 你要求一个 \(a\) 的子序列 \(b_{1\dots m}\)(可以为空),使得 \(\sum_{i=1}^m ib_i\) 的值最大。
- \(n \le 10^5\),\(|a_i| \le 10^7\)。
可以非常简单的写出 \(N^2\),\(f_{i,j}\) 表示前 \(i\) 个 \(a\),\(j\) 个 \(b\) 的答案。然后考虑用各种方式优化 DP。
这题还可以用增量法。也就是说 \(m\) 选出的 \(a\) 集合是 \(m + 1\) 的子集。我们需要用数据结构维护前缀加,后缀加 \(a_i\),单点修改,全局最大值。可以用分块维护,块内维护凸包。复杂度 \(\mathcal{O}(N\sqrt N)\)。事实上常数优秀的 \(N^2\) 已经可以通过。
CF575A
\(\{ s_n \}_{n=0}^\infty\) 是一个正整数序列。
给定 \(s_0,s_1, \dots ,s_{n-1}\),对于 \(i \ge n\),有 \(m\) 个 \(i\) 给定 \(s_i\),剩下的 \(i\) 满足 \(s_i = s_{i \bmod n}\)。
\(\{ f_n \}_{n=0}^\infty\) 同样是一个正整数序列。
\(f_0 = 0,f_1 = 1\),对于 \(i \ge 2\),\(f_i = s_{i-1}f_{i-1} + s_{i-2}f_{i-2}\),求 \(f_k \bmod p\)。
\(n,m \le 5 \times 10^4\),\(k \le 10^{18}\),\(s_i,p \le 10^9\)。
简单线性递推。由于 \(n\) 较小,直接线段树维护转移矩阵。难度不高,细节比较恶心,不能写太快了。
CF575I
- 你需要在平面直角坐标系上进行 \(q\) 次操作。
- 每次操作有两种,要么放置一个两条直角边平行于坐标轴的等腰直角三角形,要么查询某一个点被多少个三角形覆盖。
- 每个等腰直角三角形可以用四个参数 \(dir,x,y,len\) 确定,其中 \(dir \in [1,4]\) 表示三角形的方向,\((x,y)\) 表示直角的顶点坐标,\(len\) 表示直角边的长度。
- 保证所有点的坐标都是整数且 \(\in [1,n]\)。
- \(n \le 5 \times 10^3\),\(q \le 10^5\)。
经典模型,坐标转化。
\(n\) 比较小,考虑直接用二维树状数组维护。这样我们可以支持矩形加与求和。但是三角形有一条斜线不好维护。我们将坐标 \((x,y)\to (x+y,y)/(x-y,y)\),就变成了矩形。
时间复杂度 \(\mathcal{O}(q\log^2 n)\),有点卡空间,树状数组的数组要重复利用。
CF576D
- 给定一张 \(n\) 个点 \(m\) 条边的有向图。
- 一开始你在 \(1\) 号节点,你要走到 \(n\) 号节点去。
- 只有当你已经走过了至少 \(d_i\) 条边时,你才能走第 \(i\) 条边。
- 问最少要走多少条边,或判断无法到达。
- \(n,m \le 150\),\(d_i \le 10^9\)。
观察到 \(n\) 很小,\(d\) 很大,并且是经典的有向图连通性问题。直接上矩阵,\(a_{i,j}\) 表示是否能 \(i \to j\)。那么我们对于 \(m\) 条边,按 \(d\) 排序。每次求出 \(d-1\) 的矩阵,然后加边即可。由于只关心连通性,用 bitset 优化。时间复杂度 \(\mathcal{O}(m\dfrac{n^3}{\omega}\log d)\)。
CF576E
给定一张 \(n\) 个点 \(m\) 条边的无向图。
一共有 \(k\) 种颜色,一开始,每条边都没有颜色。
定义合法状态为仅保留染成 \(k\) 种颜色中的任何一种颜色的边,图都是一张二分图。
有 \(q\) 次操作,第 \(i\) 次操作将第 \(e_i\) 条边的颜色染成 \(c_i\)。
但并不是每次操作都会被执行,只有当执行后仍然合法,才会执行本次操作。
你需要判断每次操作是否会被执行。\(n,m,q \le 5 \times 10^5\),\(k \le 50\)。
动态维护二分图是经典问题,直接考虑线段树分治。
但是问题并没有完全离线,我们还要保证相对的执行顺序。所以我们遍历线段树时优先遍历左子树。到达叶子后判断是否为二分图,并在到达叶子后动态加边。由于加边的贡献区间一定在叶子表示的位置后面,所以不会有冲突。
CF578E
- 给定一个长度为 \(n\) 的只包含
L,R
的字符串 \(s\)。- 构造一个 \(n\) 排列 \(p\) 满足 \(s[p_i] \ne s[p_{i+1}](1 \le i < n)\)。
- 最小化 \(p\) 中 \(p_i > p_{i+1}(1 \le i < n)\) 的数量。
- \(n \le 10^5\),数据保证有解。
先直接贪心,将问题转化为将 L/R
串划分成最少的 LR
交替的子序列,这也可以直接贪心,开一个栈维护当前以 L/R
结尾的子序列,如果当前字符不能加入某个子序列后面就新增一个子序列。
然后考虑怎么构造答案。我们只关心子序列第一个和最后一个,只有 LL,LR,RL,RR
四种情况。每次我们选择两个出来合并,归纳下去一定可以得到答案。
CF578F
在一个 \(n \times m\) 的网格中,每个格子里都有一个呈
\
或/
状的镜子。一个合法的网格需要满足从任意一个边界段垂直射进网格中,光线会从相邻的边界段射出,同时网格中的每一段都被至少一条光线穿透。
现在网格中有 \(k\) 个位置的镜子形状不确定,求有多少种合法的网格。
\(n,m \le 100\),\(k \le 200\),答案对质数 \(p\) 取模。
结论题,大胆猜测,小心验证。
我们把 /,\
看成边,将网格交点黑白染色。那么第二个限制就是不能成环,第一个限制就是黑点或白点需要连通。
这个条件不仅必要,还是充分条件,所以并查集缩点然后跑矩阵树定理即可。
CF582D
给定质数 \(p\) 和整数 \(\alpha,A\),求满足 \(0 \le k \le n \le A\) 且 \(p^{\alpha}|\binom nk\) 的数对 \((n,k)\) 的个数。
\(p,\alpha \le 10^9\),\(A < 10^{1000}\),答案对 \(10^9+7\) 取模。
库默尔定理,\(p^{\alpha} |\binom{a+b}{a}\) 中 \(\alpha\) 的最大值等于 \(a + b\) 在 \(p\) 进制意义下的进位次数。
所以我们将 \(A\) 转化为 \(p\) 进制数,然后跑数位 DP。定义状态 \(f_{i,j,0/1,0/1}\) 表示从高到低考虑到第 \(i\) 位,有 \(j\) 次进位,是否卡上界,第 \(i-1\) 位是否进位。
CF582E
\(A,B,C,D,a,b,c,d\) 为八个布尔「变量」,其中小写字母的值等于对应大写字母的值取反。
\(\&,|\) 为两个布尔「操作符」。
布尔「表达式」为一个「变量」,或通过「操作符」连接起来的两个「表达式」。
布尔「函数」\(f(A,B,C,D)\) 为一个布尔「表达式」。
给定一个可能缺少某些「变量」和「操作符」(用
?
代替)的「函数」\(s\),并给出 \(n\) 个函数在 \(A,B,C,D\) 确定时的值。求可能的「函数」个数。\(|s|\le 500\),\(n \le 16\),答案对 \(10^9+7\) 取模。
偏基础的一题,我们先建出表达式树,然后考虑计数 DP。
由于 \(n\) 很小,并且这 \(n\) 个都是布尔函数,所以优先考虑状压。我们设计状态 \(f_{x,S}\) 表示以 \(x\) 为根的子树,\(n\) 个布尔函数值分别是 \(S\) 的方案。用 fwt 合并答案即可。
CF585E
- 有一个长度为 \(n\) 的,由 \([2,10^7]\) 内的整数组成的序列 \(a\),下标为 \(1\) 到 \(n\)。
- 要求满足条件的一个 \([1,n]\) 内的整数 \(x\) 和一个由 \([1,n]\) 内的整数组成的集合 \(S\)。
- 条件:\(x\notin S\),\(\gcd\limits_{i\in S}a_i>1\),\(\gcd(a_x,\gcd\limits_{i\in S}a_i)=1\)。
- \(n\le5\times10^5\),答案对 \(10^9+7\) 取模。
基础数论题。容斥一下,转化为求 \(\gcd(S,x) = 1\) 的方案减去 \(\gcd(S) = 1\) 的方案。分别记录 \(f(d),g(d)\),表示 \(d|\gcd\) 的方案。\(\mathcal{O}(m\ln m)\) 容斥一下即可。
对于 \(f(n) = \sum\limits_{d|n}g(d)\),即迪利克雷前缀和,可以以质数作为维度求做前缀和,类似于 fwt,时间复杂度是 \(\mathcal{O}(m\log\log m)\)。
CF585F
给定长度为 \(n\) 的数字串 \(s\) 和长度为 \(d\) 的不含前导零的数字串 \(x,y(x \le y)\)。
求存在长度至少为 \(\left\lfloor\frac{d}{2}\right\rfloor\) 的子串是 \(s\) 的子串的数字串 \(t \in [x,y]\) 的数量。
\(n \le 10^3\),\(d \le 50\),答案对 \(10^9+7\) 取模。
简单字符串题,将长度为 \(\left\lfloor\frac{d}{2}\right\rfloor\) 的子串拿出来建立 AC 自动机,然后在自动机上跑 DP 即可。
CF587D
给定一张 \(n\) 个点 \(m\) 条边的无向图,每条边有一个颜色 \(c\) 和权值 \(t\)。
你要选出一些边,使得它们是一个匹配,同时剩下的边每种颜色也是一个匹配。
同时,你要最小化选出的边的最大权值。\(n,m \le 5 \times 10^4\)。
最小化最大值,首先二分转化为判定问题。
观察一下问题限制,每条边只有选出和不选两种情况。如果两条同色边有公共点,则两边不能同时不选。两条边有公共点,两条边就不能同时选。经典的 2-sat 模型,注意要优化建图。
CF587F
- 给定 \(n\) 个字符串 \(s_{1 \dots n}\)。
- \(q\) 次询问 \(s_{l \dots r}\) 在 \(s_k\) 中出现了多少次。
- \(n,q,\sum_{i=1}^n |s_i| \le 10^5\)。
子串匹配,直接上 AC 自动机。思考一下发现没有什么有价值的好做法,考虑根号分治。
如果 \(|s_k| < T\),就将 \(s_{l\cdots r}\) 所在点 fail 树内子树加 \(+1\),然后将 \(s_k\) 扫一遍求和,对 \(l,r\) 差分后离线。复杂度是 \(\mathcal{O}(\sum T\log)\)。
如果 \(|s_k| > T\),就将 \(s_k\) 扫一遍,每到一个点就把 \(fail\) 树上的祖先全部 \(+1\)。然后前缀和统计答案。这部分时间复杂度是 \(\mathcal{O}(n)\)。
适当取 \(T\) 即可,\(T\) 略大于 \(\sqrt n\)。
CF590E
【笔记】Dilworth定理 - 7KByte - 博客园 (cnblogs.com)
CF603E
给定一张 \(n\) 个点的无向图,初始没有边。
依次加入 \(m\) 条带权的边,每次加入后询问是否存在一个边集,满足每个点的度数均为奇数。
若存在,则还需要最小化边集中的最大边权。\(n \le 10^5\),\(m \le 3 \times 10^5\)。
先考虑什么样的边集合法。首先任意图度数为奇数点的个数为偶数,所以 \(n\) 必须是偶数。扩展一下,一张图合法的充要条件是每个连通块大小都是偶数。这我们可以用调整法在构造答案的同时进行证明。
不难发现随着答案加边,答案越来越小。这样我们可以用类似维护动态最小生成树的方式用 LCT 维护。
还有一个非常神的分治做法,我愿称之为整体cdq分治()
结合了线段树分治和整体二分。定义分治 solve(l, r, L, R)
表示解决时间区间 \([l,r]\),答案区间 [L,R]
的问题。取中点 \(mid = (l+r)/2\),求出时间 \(mid\) 的答案 \(ans\)。对于左边答案 \(\ge ans\),将边权位于 \([L,ans]\) 的边加入,然后递归 solve(l, mid - 1, ans, R)
。对于右边答案 \(\le ans\),将区间 \([l, mid]\) 中边权 \(\le L\) 的边加入,然后递归 solve(mid + 1, L, ans)
。
看来复杂度非常奇怪。但简单分析 solve
的时间复杂度是 \(\mathcal{O}((r-l + R - L)\log )\),对于递归树一层的 \(\sum r - l + R - L = \mathcal{O}(n + m)\),所以时间复杂度是 \((n + m)\log ^2\)。
当然也可以用线段树分治。
CF605E
- \(n\) 个点的有向完全图。
- \(i \to j\) 的边每天出现的概率均为 \(p_{i,j}\),若 \(i = j\),有 \(p_{i,j} = 1\)。
- 每天选择一条存在的出边走过去。
- 求最优策略下从 \(1\) 到 \(n\) 的期望天数。\(n \le 10^3\)。
考虑期望 DP,设 \(f_i\) 表示从 \(i\) 到 \(n\) 的期望,然后倒推。
由于有 \(p_{i,i} = 1\),所以如果 \(f_i < f_j\),那么宁愿走自环也不会走 \(i \to j\)。所以我们只用考虑 \(f\) 小的对 \(f\) 大的贡献。
那么我们每次选出最小的 \(f\),转移给其它的 \(f\),类似于 dij 的过程。
CF611H
有一棵 \(n\) 个节点的树,节点编号为 \(1 \sim n\)。
记录这棵树的方式是记录下每条边连接的两点的编号。
现在,你不知道这些编号具体是多少,你只知道它们在十进制下的位数。
请你构造出一棵满足要求的树,或判断没有满足要求的树。\(n \le 2 \times 10^5\)。
妙妙题,暴力枚举也要动脑子。
由于只有位数信息,意味着建出的图最多只有 \(6\) 个点。
我们考虑选出 \(1,10,100,\cdots\) 等作为关键点。搜索出这 \(6\) 个关键点可能的所有的树的形态。对于其余的结点全部接到关键点上,类似于匹配的过程,直接跑网络流或匈牙利算法即可。
CF613E
给定一个 \(2 \times n\) 的矩阵,每个位置上有一个小写字母。
有一个长度为 \(k\) 的小写字符串 \(w\),询问矩阵中有多少条有向路径满足以下条件:
- 路径上的字母连起来恰好为 \(w\)。
- 不多次经过同一个位置。
- 只能向上下左右四个方向走。
\(n,k \le 2 \times 10^3\),答案对 \(10^9+7\) 取模。
非常难写的线性 DP。我们发现路径大概可以分为三部分。分开统计答案即可。
CF626G
- 有 \(n\) 个奖池,第 \(i\) 个奖池的奖金是 \(p_i\),已经有 \(l_i\) 张彩票押在上面。
- 现在你有 \(t\) 张彩票,你需要将你的彩票分配到这些奖池中,并且保证你在每个奖池中押的彩票数不能超过该奖池原有的彩票数。
- 若你在第 \(i\) 个奖池中押了 \(t_i\) 张彩票,则你中奖的概率为 \(\frac{t_i}{t_i + l_i}\),若你中奖,你可以获得这个奖池的全部奖金 \(p_i\)。
- 一共有 \(q\) 次事件,每次事件会使某个 \(l_i\) 加 \(1\) 或减 \(1\)。
- 你需要在每个事件后求出在最佳方案下你获得的奖金总数的最大期望值。
- \(n,t,q \le 2 \times 10^5\),\(p_i,l_i \le 10^3\),答案精度误差 \(\le 10^{-6}\)。
先不考虑修改操作。那么那么奖池 \(i\) 的期望收益是 \(\frac{t_ip_i}{t_i + l_i}\),增加一张彩票是 \(\frac{(t_i + 1)p_i}{t_i + l_i + 1}\)。由于总彩票 \(t\) 并不大,考虑增量法。而一个奖池随着投入增多收益递减,所以增量法是正确的。
观察到每次修改的量是 \(1\),我们猜测每次修改后引起彩票改变的量很小。事实上我们可以用不等式简单证明最多改变一张彩票。
CF627E
在一个 \(r \times c\) 的矩阵中有 \(n\) 个点,问有多少个连续子矩阵至少包含 \(k\) 个点。\(r,c,n \le 3 \times 10^3\),\(k \le 10\)。
根据套路考虑枚举矩阵的上下边界统计。我们将边界中的点按 \(y\) 排序,左边界位于 \([y_{i - 1} + 1,y_{i}]\) 之间,那么右边界的合法区间是 \([y_{i + k},m]\)。所以贡献就是 \(\sum (y_i - y_{i - 1})(m - y_{i + k} + 1)\)。
现在考虑固定上边界,移动下边界,也就是支持动态删除 \(y\),可以用链表维护。由于每删除一个元素,只会对左右 \(2k\) 个元素产生影响,所以复杂度是 \(\mathcal{O}(n^2k)\)。
CF639E
- 有 \(n\) 个问题,第 \(i\) 个问题的初始得分为 \(p_i\),所花费的时间为 \(t_i\)。
- 设 \(T = \sum_{i=1}^n t_i\),你可以按照某个顺序恰好花费 \(T\) 时间完成所有问题。
- 若你在时刻 \(x\) 完成了问题 \(i\),你可以得到 \(p_i \cdot (1 - \frac{cx}T)\) 的得分,其中 \(c\) 是一个 \([0,1]\) 的实数。
- 对于每个 \(c\),都存在至少一个可以使得分最大的最佳做题顺序。
- 对于一个做题顺序,若出现了两个问题 \(i,j\) 满足 \(p_i < p_j\) 但 \(i\) 的得分严格大于 \(j\) 的得分,则认为这种做题顺序存在悖论。
- 你需要求出最大的 \(c\),使得这个 \(c\) 对应的任意最佳做题顺序都不存在悖论。
- \(n \le 1.5 \times 10^5\),\(p_i,t_i \le 10^8\),答案精度误差 \(\le 10^{-6}\)。
答案具有单调性,直接二分答案。
观察一下,最佳顺序与 \(c\) 无关,我们按 \(\frac{p}{t}\) 排序,然后贪心即可。
CF639F
给定一张 \(n\) 个点 \(m\) 条边的初始无向图。
\(q\) 次询问,每次询问给定一个点集 \(V\) 和边集 \(E\)。
你需要判断,将 \(E\) 中的边加入初始无向图之后,\(V\) 中任意两个点 \(x,y\) 是否都能在每条边至多经过一次的情况下从 \(x\) 到 \(y\) 再回到 \(x\)。
\(n,m,q,\sum |V|, \sum |E| \le 3 \times 10^5\),强制在线。
比较难写的 DS 题。
问题转化一下,就是在加边后,边双缩点后 \(V\) 在一个边双连通分量中。
我们先将原图边双缩点成树,对于每次询问,建出 \(V\) 和 \(E\) 的端点构成的虚树,将 \(E\) 的边加入,再跑一次边双缩点即可。
CF666D
给定平面直角坐标系中的四个整点,问是否存在四个整数坐标,满足:
第 \(1\) 个点能够仅通过竖直或者水平移动到达第 \(1\) 个坐标(也就是说横坐标或者纵坐标相同),第 \(2, 3, 4\) 个点类似。
且这四个新的整数坐标形成了面积非负的正方形的四个顶点(也就是说不能重合)。
且这个正方形的边必须平行于坐标轴(不是斜着的)。如果存在这样的四个坐标,则尽量最小化对应点移动的距离的最大值。
(形式化地说,假设第 \(i\) 个点移动的距离为 \(d_i\),你需要最小化 \(\max\limits_{i=1}^{4} d_i\))如果不存在这样的坐标,输出
-1
。
否则输出最小化的 \(\max\limits_{i=1}^{4} d_i\),以及那四个坐标。有 \(t\) 组询问。
数据很小,所以不用考虑复杂度,但要保证正确性。
根据抽屉原理,至少有两个点是竖直运动或左右运动。我们枚举这两条线,然后大力讨论一下即可。
CF671D
给定一棵以 \(1\) 为根的树,给定 \(m\) 条路径,每条路径覆盖 \(x_i\) 到 \(y_i\),权值为 \(w_i\),保证 \(y_i\) 是 \(x_i\) 祖先,求覆盖整棵树的最小路径权值和。
首先我们不难想出一个一个树形 DP,用 \(f_{x,d}\) 表示覆盖了 \(x\) 的子树,并且向上衍生到深度 \(d\) 的答案。根据套路我们可以直接线段树优化 DP,时空复杂度是 \(\mathcal{O}(n\log n)\),空间可能有点卡。
我们可以换一种方式维护。对于每个 \(x\),开一个堆维护二元组 \(\{value,dep\}\) 表示有一个代价为 \(value\) 的 \(f_{x,d}\) 方案。合并子树时,只用支持整体加即可。启发式合并可以做到时空复杂度 \(\mathcal{O}(m\log ^2 m + n) - \mathcal{O}(n + m)\)。用左偏树可以做到 \(\mathcal{O}(m \log m + n) - \mathcal{O}(n + m)\)。
CF643F
【笔记】简单信息量计算 - 7KByte - 博客园 (cnblogs.com)
CF643G
- 给定一个长度为 \(n\) 的序列和一个整数 \(p\)。
- 有 \(m\) 个操作,操作要么是区间赋值,要么是询问区间内出现次数至少占 \(p\%\) 的数。
- 输出询问的答案时,可以包含错的数,也可以重复输出,但对的数一定要在答案中,且输出的数的个数不超过 \(\lfloor \frac{100}{p} \rfloor\)。
- \(n,m \le 1.5 \times 10^5\),\(20 \le p \le 100\)。
经典问题。有一种求区间绝对众数的摩尔投票法。
我们分析一下这种方法的本质。如果出现我们每次选出 \(100 / p\) 个两两不同数同时删除,最多会删除 \(p\%\) 的数,而出现次数 \(\ge p \%\) 的数一定不会被删完。并且删除后最多留下 \(\lfloor \frac{100}{p} \rfloor\) 个数,用线段树维护这最多 \(5\)个数的结果即可。
CF679E
定义一个正整数是坏的,当且仅当它是 \(42\) 的次幂,否则它是好的。
给定一个长度为 \(n\) 的序列 \(a_i\),保证初始时所有数都是好的。
有 \(q\) 次操作,每次操作有三种可能:
1 i
查询 \(a_i\)。2 l r x
将 \(a_{l\dots r}\) 赋值为一个好的数 \(x\)。3 l r x
将 \(a_{l \dots r}\) 都加上 \(x\),重复这一过程直到所有数都变好。\(n,q \le 10^5\),\(a_i,x \le 10^9\)。
观察到一个数由好变坏的次数是 \(\log\) 级别。所以我们直接上均摊线段树即可。
CF685C
给定一个立体直角坐标系上的\(n\)个整点,求一个整点满足到这\(n\)个整点的曼哈顿距离的最大值最小。
二分答案,然后列出不等式,最后解不等式。有一些构造的技巧,具有启发性。
CF698D
- 平面上有 \(k\) 个人和 \(n\) 个怪物,每个人手中有一支箭。
- 每支箭可以往任意方向射出,击中这个方向上的第一个怪物后,箭和怪物都会消失。
- 问有多少怪物可能会被击中。
- \(k \le 7\),\(n \le 10^3\)。
考虑到 \(k\) 非常小,作为这题的切入点。
我们枚举目标怪物,再 \(k!\) 枚举我们射箭的顺序,然后倒叙模拟。先将目标放入队列。每次弹出队首,并将当前射手到目标路径上的其它怪物加入队列即可。
CF700E
给定一个字符串 \(S\),要求构造字符串序列 \(s_1,s_2,\ldots,s_k\),满足任意 \(s_i\) 都是 \(S\) 的子串,且任意 \(i\in[2,n]\),都有 \(s_{i-1}\) 在 \(s_i\) 中出现了至少 \(2\) 次(可以有重叠部分,只要起始、结尾位置不同即可)。
求可能的最大的 \(k\) 的值(即序列的最大可能长度)。\(n \leq 2 \times 10^5\)。
一个串的子串问题,考虑 SAM。一个等价类中的所有子串等价,可以反证一下,不等价则可以划分出新的等价类。
这样设计状态 \(f_i\) 表示等价类 \(i\) 的最大的 \(k\) 值。由于父子的 \(f\) 值最大只有 \(1\) 的差值,所以指针指针记录一下 \(f_i\) 相等的最浅祖先优化转移即可。
CF704B
- 有 \(n\) 个元素,第 \(i\) 个元素有五个参数 \(x_i,a_i,b_i,c_i,d_i\)。
- 你需要求出一个 \(1 \sim n\) 的排列 \(p\),满足 \(p_1 = s, p_n = e\),同时最小化这个排列的权值。
- 一个排列的权值为 \(\sum_{i=1}^{n-1} f(p_i, p_{i+1})\),其中 \(f(i,j)\) 的值有两种情况:
- 若 \(i > j\),则 \(f(i,j) = x_i - x_j + c_i + b_j\)。
- 若 \(i < j\),则 \(f(i,j) = x_j - x_i + d_i + a_j\)。
- \(n \le 5 \times 10^3\),\(s \ne e\),\(1 \le x_1 < x_2 < \cdots < x_n \le 10^9\),\(1 \le a_i,b_i,c_i,d_i \le 10^9\)。
我们让 $a,c $ 加上 \(x\),\(b,d\) 减去 \(x\),就可以忽略 \(x\)。
对于排列,\(p_i \to p_{i + 1}\) 连边,则恰好构成一条链。我们定义状态 \(f_{i,j}\) 表示前 \(i\) 个点,构成 \(j\) 个链的最优答案,枚举 \(i = 1 \to n\) 依次考虑加入一个数转移即可。
这题还可以使用增量法,初始化 \(s \to e\),每次向链中插入一个点得到答案。
CF704C
- 给定 \(m\) 个布尔变量 \(x_1, x_2, \ldots, x_m\),以及 \(n\) 个形如 \(x_i\) 或者 \(x_i \ \mathrm{or} \ x_j\) 的布尔表达式,其中规定 \(x_{-i}=\lnot x_i\)。并且,保证 \(x_i\) 和 \(x_{-i}\) 在所有的布尔表达式中一共只会出现最多两次。
- 请你求出,在一共 \(2^m\) 种布尔变量取值的情况下,有多少种情况,使得所有布尔表达式的值的异或为 \(1\)。此处认为,\(\rm True\) 为 \(1\),\(\rm False\) 为 \(0\)。
- 由于结果可能过大,请输出答案模 \(10^9+7\) 的结果。
- \(1 \leq n,m \leq 10^5\)。
注意到关键条件每个 \(x_i\) 最多出现 \(2\) 次,每个布尔表达式最多两个变量,所以我们将表达式看成点,两个表达式如果有相同变量就连边。
这样我们就会得到若干个环和链,环我们可以破环成链做。直接计数 DP,状态 \(f_{i,0/1,0/1}\) 表示考虑到链上第 \(i\) 个点,表达式的异或值是 \(0/1\),上一个变量是 \(0/1\) 的方案,简单转移一下即可。注意边界。
CF708D
- 给定一张 \(n\) 个点 \(m\) 条边的网络,源点为 \(1\),汇点为 \(n\)。
- 对于每条边,有容量 \(c\),当前流量 \(f\)。
- 但这个图是错误的,可能存在 \(c < f\),或者流量不守恒的情况。
- 你每次操作可以将某条边的 \(c\) 或 \(f\) 加 \(1\) 或减 \(1\)。
- 请你用最少的操作次数将图变成一个正确的网络。
- \(n,m \le 100\),\(c,f \le 10^6\),\(1\) 没有入边,\(n\) 没有出边。
上下界费用流模型。我们先强制每条边流 \(f\),然后用费用流将流调整至合法。
上下界的求法是先强制每条边流下界,然后建立超级源汇点进行补流。注意到原图有源汇,加入一条汇点到源点的费用为 \(0\),容量无限的边。
CF708E
有一个 \((n+2) \times m\) 的网格。
除了第一行和最后一行,其他每一行每一天最左边和最右边的格子都有 \(p\) 的概率消失。
求 \(k\) 天后,网格始终保持连通的概率。\(n,m \le 1.5 \times 10^3\),\(k \le 10^5\),答案对 \(10^9+7\) 取模。
不难直接写出 DP 方程 \(f_{i,l,r}\) 表示前 \(i\) 行,第 \(i\) 行保留的区间 \([l,r]\),并且区间与起点连通的方案。然后转移到 \(f_{i + 1,l',r'}\),条件是 \(r\le l' \land l \ge r'\)。
这做法复杂度非常高,并且这状态数看起来就很没前途()
事实上我们只关心所有 \(f\) 的和,所以我们记录前缀和 \(s_{i,j} = \sum\limits_{r\le j}f_{i,l,r}\)。
本来是用 \(s\) 优化转移到 \(f\),但整理一下公式我们发现,可以直接从 \(s_i \to s_{i + 1}\),并且最后的答案也只关心 \(s_{n,m}\),这样我们可以在 \(\mathcal{O}(nm)\) 的时间解决问题。
CF1610F
给定一张含 \(n\) 个点 \(m\) 条边的无向图,结点编号为 \(1\) 到 \(n\)。
每条边有边权 \(w_i\),而 \(w_i\) 只能等于 \(1\) 或 \(2\)。蓝想要给每条边定向,使得图尽可能的可爱。
图的可爱程度定义为图中好的结点的数量。一个结点 \(v\) 是好的,当且仅当令 \(d^+(v)\) 为 \(v\) 所有出边的权值和,令 \(d^-(v)\) 为 \(v\) 所有入边的权值和,有 \(|d^+(x)-d^-(x)|=1\)。
试着帮蓝找到图的最大可能可爱程度,并且给出任意一种构造方案。\(1 \leq n,m \leq 3\times10^5,1 \leq u_i,v_i \leq n,\mathbf{w_i\in\{1,2\}}\)。
先估计一个答案上界。我们将一条边反向,度数奇偶性不会改变。所以一个点为好点的必要条件是直接相连的边的 \(\sum w\) 为奇数。
我们猜测这就是充分条件,考虑归纳证明。如果存在两条边 \((x,y),(y,z)\) 的 \(w\) 相同,那么我们让两条边同向,每个点的 \(\sum w\) 不变。那么可以看成将边缩成 \((x,z)\)。一直缩下去直到不能再缩。这样每个点度数 \(\le 2\)。图由若干个环和单链构成,这样的图可以轻易构造出答案,然后倒推出初始状态即可。
CF1556F
有 \(n\ (n\le14)\) 个人,两两之间会打比赛。每人有一个实力值 \(a_i\),在 \(i\) 与 \(j\) 的比赛中, \(i\) 有 \(\frac {a_i}{a_i+a_j}\) 的概率获胜,其他情况则是 \(j\) 获胜。\(i\) 在与 \(j\) 的比赛中获胜则称 \(i\) 打败了 \(j\)。若 \(i\) 打败了 \(j\),\(j\) 打败了 \(k\),则认为 \(i\) 也打败了 \(k\)。若 \(i\) 打败了除了他自己以外的所有人,则称 \(i\) 是一个 Winner(是否打败了自己不要求),注意 Winner 可能有多个。现在你需要求出 Winner 的期望数量,对 \(1e9+7\) 取模。
数据范围很明显的状压。我们定义状态 \(f_{S}\) 表示 \(S\) 的子图中,任意两点可达的期望。
那么可以简单容斥得到方程,我们枚举 \(T\subset S\),转移 \(f_T\times P \to f_S\),其中 \(P\) 表示所有集合 \(T\) 和 \(S\setminus T\) 之间的边全部是由 \(T\) 连向 \(S\setminus T\) 的概率。
这样时间复杂度是 \(\mathcal{O}(n^23^n)\),实际跑不满可以通过。
CF1149D
给定 \(n\) 个点 \(m\) 条边的无向图,只有 \(a,b\) 两种边权 \((a < b)\),对于每个 \(i\),求图的所有的最小生成树中,从 \(1\) 到 \(i\) 距离的最小值。
根据 Kruscal 算法,先连 \(a\) 边再连 \(b\) 边,将 \(a\) 边连成的连通块缩成一个点,走过的 \(b\) 边必须是不同连通块间的并且不能成环。我们可以直接状压 \(f_{x,S}\) 表示走到 \(x\),经过的连通块集合为 \(S\) 的最短路径。
有一个很关键的观察,我们记录 \(S\) 是为了避免从一个连通块走出又走回来,如果这样,至少要走 \(2b\) 的路,如果连通块大小 \(\le3\),路径最长为 \(2a< 2b\),所以我们只用状压大小 \(\ge 4\) 的连通块,然后跑最短路,时间复杂度为 \(\mathcal{O}(2^{n/4}(n+m)\log)\)。