CF 两千分壹佰道

感觉,一个壹佰道就够用了,要 CF 上上分了。题解含量 \(0\),放心食用,主要是锻炼做题速度。

目前进度:65/100。

vp 时或赛时没做出来时间用 INF 表示。

CF评分网站

[CF1811F] Is It Flower?/洛谷/CF

2100 difficulty/26' time/4 submit

这东西看起来就很点双,先缩个点双。取 \(x = \sqrt{n}\),则有 \(x\) 个点双,每个点双大小都为 \(x\)\(m = x \times (x + 1)\);有 \(x\) 个四度点,且这些四度点在一个点双中,其余点都为二度点。最后判一下图是否联通即可,可以从随便找个点做 tarjan,如果有点没有 dfn 值,则图不连通。硬判即可,做到单次 \(\mathcal O(n)\)

[CF1772F] Copy of a Copy of a Copy/洛谷/CF

2000 difficulty/18' times/3 submit

注意到没有撤回操作,一个点只能操作一次,所以排好序后能操作的点的数量一定是单调不增的,可以直接暴力的计算每个图片有几个能操作的点,再暴力对比怎么变得,这样做到 \(\mathcal O(k \log k + nmk)\),已经足够通过了。

[CF1790G] Tokens on Graph/洛谷/CF

2300 difficulty/46' times/1 submit

很典型的 CF 题,一万个 CornerCase,不过竟然一次考虑全了。由于一个棋子不能连续两次移动,要使最终有棋子到达 \(1\) 号节点,先将 \(1\) 设为关键点,特判掉上来 \(1\) 已经有棋子的情况。从 \(1\) 开始做 flood-fill 扩展,只有关键点能够入队,并计算每个节点到关键点的距离。如果 \(1\) 所在的这个连通块有两个及以上的棋子就直接赢了,如果一个棋子都没有就直接输了。考虑一个棋子的情况,如果剩余的其他棋子随便一个能够到达一个大小至少\(2\) 的关键点连通块,那就可以反复横跳操作无数次,然后就可以一直让 \(1\) 走;否则计算那些棋子可以移动一步,看总和是否能够支持 \(1\) 所在连通块的棋子到达 \(1\)。需要特别注意一个位置既是关键点又有棋子的情况,代码细节较多。

[CF1838D] Bracket Walk/洛谷/CF

2100 difficulty/73' times/4 submit

怎么判无解要对称着判。首先 \(n\) 为奇数显然不合法,第一个括号为右括号或最后一个括号为左括号不合法。考虑什么时候会回头走,即两个相邻的括号相同。如果判掉上述两个显然的情况,并且序列中不存在两个相邻的相同括号,那么形态必然为 ()()()...(),合法。如果只有一种括号有两个相邻的相同括号,那么必然不合法,因为有一种会数量多。剩下的就是两种括号都有两个相邻相同的情况。如果第一个右括号组在第一个左括号组前,或者最后一个左括号组在最后一个右括号组后面,那么也不合法,正确性显然。最后一种情况形如 ((...()...)),其中括号组的长度是几都无所谓,因为可以在一个括号组反复横跳把后面需要的额外补全括号数填满。于是要做的是动态维护括号组的信息。可以使用四个 set 简单维护左括号/左括号组/右括号/右括号组,修改直接在原串和 set 上修改信息即可。于是做到 \(\mathcal O(m \log n)\)

[CF1791G2] Teleporters/洛谷/CF

1900 difficulty/5'+44' times/1+6 submit

简单版过于简单,贪就完了。困难版怎么还不会二分答案啊?注意到只有第一个传送器的位置是必须以 \(0\) 为起点,其他的传送器都可以贪心的选取从 \(0\) 还是 \(n+1\) 为传送点,于是可以想到枚举起点。如同 \(G1\) 一样,贪心计算出每个传送门需要的花费,排序后做前缀和,这样可以 \(\mathcal O(1)\) 的获得走多少传送门的最低花费。然后二分答案看以 \(i\) 为第一个进的传送门最多能走几个即可。于是做到 \(\mathcal O(n \log n)\)

[CF1741G] Kirill and Company/洛谷/CF

2200 difficulty/INF/1 submit

首先没有车的最多 \(6\) 个人,这个数据范围启示进行状压。设 \(b_{i,S}\) 表示在第 \(i\) 个点任意一个有车的人能不能带 \(S\) 这些人回去,\(f_{S}\) 表示 \(S\) 这个集合的没车的人能不能满足都被送回家。前者可以 bfs 扩展找到最短路径,并同时记录是否可行;后者用前者做一个类似 01 背包的可行性 DP 转移。于是总复杂度为 \(\mathcal O(2^km + 3^kf)\),后者为枚举子集复杂度,不过暴力枚举也能过。

[CF118E] Bertown roads/洛谷/CF

2000 difficulty/16' times/3 submit

平凡。将边改为单向边后无解,当且仅当一个边双到达了另一个边双,另一个边双不能反向回来,于是无解的充要条件为原无向图中存在桥,跑 tarjan 求即可。输出方案可以一边 tarjan 一边记录,在 dfs 树上合法构造方案的方向即树边为爹到儿子,返祖边为儿子到祖先。

[CF1855C] Dual/洛谷/CF

1900 difficulty/12'+53' times/3+3 submit

如果全是正数,做前缀和,总操作为 \(n - 1\) 次;如果全是负数,做后缀和,总操作为 \(n - 1\) 次。问题转化为如何将整个序列在 \(12\) 次内转为全正/负。考虑用两个正负形相反的数,如何相互操作使得正负形相同,极限情况为 \(1\)\(-20\),发现对 \(1\) 倍增 \(5\) 次即可得到 \(32\) 使得 \(-20 + 32 > 0\)。如果负数和正数数量较少的那个数量 \(\leq 7\),那么就先倍增数量多的那种数中绝对值最大的那个,然后给较少的那一种全都加上倍增完后的这个数,再做前缀和或后缀和即可。否则说明负数和正数的数量都 \(\geq 8\) 并且 \(\leq 12\),直接拿绝对值最大的那个数作为加数,给所有另一种正负类型的数暴力加至所有数为同一符号即可,然后再做前缀和或后缀和。好久不做构造吃罚时这么多。

[CF1729E] Guess the Cycle Size/洛谷/CF

1800 difficulty/21' times/2 submit

我好像,有脑子了。直接二分看什么时候出 \(-1\) 是不能解决的,因为 \(2^{50} < 10^{18}\),于是就没有什么好的方法了。转换一下思路,因为在环上,如果能够知道两个点两个方向的距离,那么答案就是两段距离的和。注意到交互库回答两个点之间的距离两个方向是等距离的,所以考虑枚举 \(i\),询问 ? 1 i? i 1,如果两段距离不相等直接输出和;如果交互库返回 \(-1\),直接输出 \(i - 1\)。这样错误率能够到达 \(\dfrac{1}{2^{25}}\),如果还能挂就可以买彩票了。

[CF1729G] Cut Substrings/洛谷/CF

2100 difficulty/28' times/1 submit

首先可以用 KMP 把所有子串的位置都提出来,然后考虑重叠的子串,如果有若干个重叠的子串,只需要从中选择删除掉一个部分即可。记 \(f_i\) 表示让前 \(i\) 个出现子串的位置都没有子串的最小删除次数,转移即为 \(f_i = \min {(f_j + 1)}\),满足条件的 \(j\) 即为和 \(i\) 无交,方案数转移的时候顺便统计即可。对于每个位置暴力枚举无交的其他位置,单次做到 \(\mathcal O(n + n^2)\)

[CF1708D] Difference Array/洛谷/CF

1900 difficulty/36' times/3 submit

直觉上差分次数做的越多前面的零的数量就会越多,所以可以记录零的数量,然后暴力差分求序列即可,使用优先队列可以简单实现模拟过程。事实上我们要使差值尽可能慢的变成零,最优秀的选择是构建斐波那契数列,然而遗憾的是这样也最多操作 \(\log n\) 次,所以最后复杂度毛估估是个 \(\mathcal O(n \log n)\),感觉分析复杂度好难。

[CF1759G] Restore the Permutation/洛谷/CF

1900 difficulty/57' times/1 submit

怎么,这么墨迹?要求出字典序最小的,填数的位置又依赖于大小关系,所以考虑值域上从大到小插入。首先可以直接把 \(b_i\) 放到 \(p_{2i}\) 的位置上。记 \(v_{b_i} = 2i - 1\),假如说当前考虑到一个数 \(i\)\(i\)\(b\) 中出现过,则将 \(v_i\) 加入决策集合;否则就要在 \(p\) 中插入 \(i\),那么考虑放到最靠后的位置上,即最大的 \(v\);如果说当前时刻要插入新的 \(i\),而决策集合中又没有值,则无解。需要快速加入删除决策,从决策中找出最大值,可以使用 set 做到 \(\mathcal O(n \log n)\)

[CF1797D] Li Hua and Tree/洛谷/CF

1900 difficulty/27' times/2 submit

模拟。重儿子可能是动态改变的,所以对于每一个节点要动态维护它的所有儿子决策集合。注意到需要维护的信息只有子树大小,子树和,儿子和父亲关系。先一遍 dfs 统计出来,然后按照题意模拟修改即可。要支持已知单个信息的修改(转化为从决策中删除后再插入),快速查询一个节点的重儿子(从决策中找出最大值),可以用 set 做到 \(\mathcal O(m \log n)\)

[CF1714F] Build a Tree and That Is It/洛谷/CF

1900 difficulty/56' times/2 submit

核心在于无解的充要条件,感觉构造整棵树有点答辩了。最终形态一定形如 \(a \leftrightarrow b\),然后 \(c\) 在中间的一个位置延伸出来一部分(这一部分长度也可能为 \(0\),即在 \(a \leftrightarrow b\) 的路径上)。不妨记交汇在 \(d\) 这个位置(那么可能 \(c\)\(d\) 是同一个点),记 \(l_1 = (a,d),l_2 = (b,d),l_3 = (c,d)\),那么有 \(l_1 + l_2 + l_3 = 2 \times (d_1 + d_2 + d_3)\),然后就可以求出 \(l1,l2,l3\)。这时候已经注意到如果 \(d_1 + d_2 + d_3\) 为奇数或者 \(l_1 + l_2 + l_3 \geq n\) 或者 \(l\) 有负数的出现则无解。还有一个部分在于能够发现 \(c\) 点只能有最多一个,不然会出现“重合”的现象,也是不合法的,即 \(l\) 只能有最多一个是 \(0\)。其他情况均有解。构造答案是简单的,先构造出上述的类似三连通的结构,剩下的点随意连即可。

[CF1854B] Earn or Unlock/洛谷/CF

2200 difficulty/INF/5 submit

具体用哪一张牌来解锁到当前局面是无关紧要的,重要的是当前恰好解锁到了哪一张牌。如果当前能够解锁到 \(i\),那么答案就能够更新到 \(\sum a_i - (i - 1)\)。注意到恰好解锁的卡牌可能超过 \(n\),但是不会超过 \(2n\),所以最后枚举答案要扩大范围。使用可行性 DP,设 \(f_i\) 表示是否有一种方式能够恰好解锁 \(i\) 张牌,边界 \(f_1 = 1\),转移即为 \(f_i |= f_{i - a_j}\),直接做是 \(\mathcal O(n^2)\) 的,可以使用 bitset 优化做到 \(\mathcal O(\dfrac{n^2}{w})\)

[CF1841D] Pairs of Segments/洛谷/CF

2000 difficulty/41' times/1 submit

转化为如何选取最多。最终形态是若干个两两线段的并最后无交,注意到别致的数据范围,直接 \(\mathcal O(n^2)\) 枚举线段看是否有交,如果有则将其的并放入到决策集合中。接下来不要想 DP,直接按右端点为第一关键字,左端点为第二关键字升序排序后贪心的选取即可。如果说从新集合中选择了 \(k\) 条线段,那么就是旧集合删除 \(n - 2k\) 个线段。瓶颈在于排序,单次做到 \(\mathcal O(T \log T)\),其中 \(T = n^2\)

[CF1822G] Magic Triples/洛谷/CF

2200 difficulty/12'+38' times/1+1 submit

对于 easy version,值域非常小,取 \(a_i = \dfrac{a_j}{b},a_k = a_j \times b\),注意到有 \(b \mid a_j\),因此可以直接枚举 \(a_j\) 的因子,复杂度为 \(\mathcal O(n \sqrt{V})\)。hard version 拉大了 \(a\) 的值域,考虑数据范围分治,设定阈值 \(B\),对于 \(\leq B\) 沿用之前的做法,对于 \(> B\) 的部分换用枚举 \(b\) 看是否存在合法的 \(a_i\)\(a_k\),这样枚举 \(b\) 的量级为 \(\mathcal O(\dfrac{V}{B})\),于是做到了 \(\mathcal O(n \max(\sqrt{B},\dfrac{V}{B}))\),平衡一下发现取 \(B = 10^6\) 最合适。

[CF1364D] Ehab's Last Corollary/洛谷/CF

2100 difficulty/27' times/4 submit

如果原图是个树,交替染色一定有一种颜色数量能够取到 \(\lceil \dfrac{k}{2} \rceil\)。否则图中一定存在环,寻找一个图中最小的环,这样一定是一个简单环。如果环长不超过 \(k\),那么直接输出这个环即可;否则在这个环上交替染色,同样至少可以取到 \(\lceil \dfrac{k}{2} \rceil\)

[CF858E] Tests Renumeration/洛谷/CF

2200 difficulty/79' times/4 submit

solution

[CF1661D] Progressions Covering/洛谷/CF

1900 difficulty/50' times/1 submit

上来能够先注意到对于第 \(i\) 个位置能够进行的选择为 \(1 \sim \min(i,k)\)。正着做是有后效性的,倒着做是当前必须选了,就可以直接进行贪心。通过倒序扫描,简单维护每个位置选择进行多少次操作,当前的长度为 \(k\) 的段总共进行了几次操作就可以做到 \(\mathcal O(n)\),非常典型的正难则反的题目。

[CF1283F] DIY Garland/洛谷/CF

2200 difficulty/63' times/3 submit

第一个出现的点是根,从未出现过的点是叶子,一个点的出现次数是其儿子的数量。考虑贪心模拟这个过程,后出现的点链接的一定是当前决策集合中最小的那个点,用小根堆即可快速决策。倒序扫描序列,起初的决策集合即为所有的叶子,如果一个点的儿子都已被加入完毕,那么将这个点放入到决策集合中,模拟这个过程即可,做到 \(\mathcal O(n \log n)\)

[CF1851G] Vlad and the Mountains/洛谷/CF

2000 difficulty/INF/2 submit

第一把 div3 没有做出来的题,现在一看也不难啊/kk。因为计算方式不带绝对值号,所以从 \(s\) 出发初始能量为 \(e\),能够到达高度不超过 \(h_s + e\) 的点。维护连通性,询问和加边放在一起,对于加边权值为 \(\max(h_x,h_y)\),对于询问权值为 \(h_s + e\),全部离线下来从小到大排序,并查集维护即可。瓶颈在于给所有操作排序,做到 \(\mathcal O((m+q) (\log (m+q) + \alpha (n)))\)

[CF1833F] Ira and Flamenco/洛谷/CF

1700 difficulty/39' times/1 submit

分不高,但是是数数还是想记一下。因为题目中的限制,使得从小到大排序后选的是值域上连续的一段,即选择的一整段减去一个值 \(d\) 后得到的是一个 \(1 \sim m\) 的排列,因此不会出现跨过中间一部分值选两边的情况。所以可以去重统计每种数的个数,改变变量含义,\(n\) 为数的种类,\(s_i\) 为第 \(i\) 种数的个数,\(a_i\) 为第 \(i\) 种数的值,最后的答案就是 \(\sum_{i = 1}^{n} [a_{i+m-1} - a_i < m] \Pi_{j=i}^{i+m-1} s_j\)。可以前缀积维护,现求逆元即可,做到 \(\mathcal O(n \log V)\)

[CF1690G] Count the Trains/洛谷/CF

2000 difficulty/INF/1 submit

vp 在线降智,不会使用 STL。维护位置和速度的一个二元组,按位置为第一关键字,速度为第二关键字升序排序,如果一个的速度比它前面的速度大,就可以移除这个点。修改考虑插入修改后的元素,如果前驱比当前的速度慢,就移除插入的这个元素;否则暴力向后跳,删除掉速度比它大的,直到遇到一个位置速度比插入的元素小。注意到一次插入只会增加一个元素,删除至少删掉一个元素,势能只减不增,因此是正确的。需要支持快速插入,查前驱后继,用 set 维护做到 \(\mathcal O(n \log n)\)

[CF1702G] Passable Paths/洛谷/CF

2000 difficulty/40' times/1 submit

和树形态无关,可以先定成有根树。将所有点集中的点标记,提取出来路径,如果路径有多于两个端点一定不合法,只有一个端点一定合法(关键点都在一条根链上),两个端点就求端点路径上的点的数量是否为 \(m\)。需要做到快速单点修改,路径和查询,子树和查询,可以无脑树剖加树状数组做到 \(\mathcal O((m + q) \log n)\)

[CF1619G] Unusual Minesweeper/洛谷/CF

2000 difficulty/9' times/1 submit

容易想到把会一块爆炸的合并,可以按横坐标排序做一遍,按纵坐标排序做一遍,并查集维护即可,顺便记录该连通块中最早爆炸的点。贪心的从爆炸最晚的开始点燃,直到当前点燃炸弹数不多于枚举到的炸弹爆炸时间即为答案,于是做到单次复杂度 \(\mathcal O(n \log n + n \alpha(n))\)

[CF1077F] Pictures with Kittens/洛谷/CF

2100 difiiculty/17' times/4 submit

无解为 \(n/k>m\)。设 \(f_{i,j}\) 表示前 \(i\) 个数选 \(j\) 个数,且必须选择 \(a_i\) 的最大和,最终答案即为 \(\max_{i=n-k+1}^{n} {f_i}\),转移方程为 \(f_{i,k} = \max_{j = i - k}^{i - 1}{f_{j,k-1}} + a_i\)。看到 \(\max\) 并且是逐层转移,显然可以单调队列优化,队头决策小于 \(i - k\) 的时候不能使用,弹出队头;尝试插入队尾时尾部的 \(f_{tail,k-1}\) 不大于 \(f_{i,k-1}\) 决策不优弹出队尾。于是做到 \(\mathcal O(nk)\)。需要注意的是此题必须初始化 f 数组为一个极小值,但是为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?为什么呢?

[CF1674E] Breaking the Wall/洛谷/CF

2000 difficulty/INF/2 submit

分讨/cf。根据样例猜测怎么选。肯定是确定让两个数非正,记这两个数为 \(a_i\)\(a_j\),那么最好想的是操作这两个数互不关联,即 \(|i - j| > 2\),一直怼 \(-2\) 就好了,那么答案就是 \(\lceil \dfrac{a_i}{2} \rceil + \lceil \dfrac{a_j}{2} \rceil\)。如果选择的两个数相邻距离为 \(2\),即 \(|i - j| = 2\),注意到无论操作两个数相夹的那个数还是单独操作一个数,都是使目标 \(-2\),那么答案为 \(\lceil \dfrac{a_i + a_j}{2} \rceil\)。如果两个数相邻,会有两种情况:对着一个 \(-2\),这个数变成非正时靠 \(-1\) 就能把另一个数也变为非正;对着一个数操作一会 \(-2\),再对另一个数操作一会 \(-2\)(即对前者 \(-1\))。前者的答案为 \(\lceil \dfrac{\max{(a_i,a_j)}}{2} \rceil\),后者的答案为 \(\lceil \dfrac{a_i + a_j}{3} \rceil\)。两者的分界线在于 \(\max{(a_i,a_j)} \geq \min{(a_i,a_j)} \times 2\)。最后对三种答案取 \(\min\) 即可。事实上第一种情况只需要全局的两个最小值即可,因为如果选到的两个位置 \(|i - j| \leq 2\),那么选剩下两个情况操作一定是更优的,换用别的数用第一种情况一定不优。于是就做到了 \(\mathcal O(n)\)

[CF1674G] Remove Directed Edges/洛谷/CF

2000 difficulty/39' times/1 submit

能够转移的边合法当且仅当存在一种删边方法能够保留这条边,这就需要对于边 \((u,v)\)\(u\) 的出度大于 \(1\)\(v\) 的入度也大于 \(1\),否则这条边一定要拿来删除的。剩下的工作是在删边后的 DAG 上找一条最长路,注意到 DAG 删边后一定还是 DAG,最长路用拓扑排序做,可以一边拓扑一边判转移是否合法,于是就可以 \(\mathcal O(n)\)

[CF1513D] GCD and MST/洛谷/CF

2000 difficulty/61' times/9 submit

线段树边界写错,狂暴提交的我是小丑。solution

[CF1108F] MST Unification/洛谷/CF

2100 difficulty/27' times/2 submit

考虑最小生成树的过程,如果加入一条边 \((u,v)\) 能够等效替代原树的边,那么替换掉的边一定和这条边的边权相等,并且要保持图仍联通,那么这条边一定在 \(u \to v\) 的路径上。先跑出最小生成树后,倍增或树剖维护最小生成树上的最大边权,然后遍历每一条边看是否能够替代,能替代就需要对这条边进行一次操作使得符合题意。于是做到 \(\mathcal O(m \log n)\)

[CF1304E] 1-Trees and Queries/洛谷/CF

2000 difficulty/27' times/1 submit

只有三种可能,\(x \to y\)\(x \to a \to b \to y\)\(x \to b \to a \to y\),倍增求距离分讨即可,做到 \(\mathcal O((n + m) \log n)\)

[CF1399E] Weights Division/洛谷/CF

2200 difficulty/19'+85' times/2+6 submit

简单版不带边的花费,先边转点,记录每个点 \(i\) 的子树里有 \(lef_i\) 个叶子,路径和拆贡献变为 \(\sum_{i = 2}^{n} lef_i \times val_i\),然后大根堆模拟贪心即可,每次取出堆顶,即最大的 \(lef_i \times val_i\),然后操作完后将 \(val_i\) 整除 \(2\) 后放回堆中。一条边最坏操作 \(\log\) 次,最坏情况即为将所有边变成零,所以复杂度 \(\mathcal O(T \log T)\),其中 \(T = n \log V\)

困难版有两种边,单次操作花费分别为 \(1\)\(2\)。本以为有高妙做法,结果还是暴力,复杂度还算假了,做了挺久。将边按类型分开做一遍简单版的过程,这样得到了只用一种类型的边分别的最小操作次数的操作序列。枚举其中一种边使用多少次,然后统计另一种边的减小边权量的前缀和数组,在上面二分即可。分别做简单版的过程是必要的,如果只是简单的用 set 维护所有边选择的决策集合复杂度并不正确。这样做到 \(\mathcal O(T \log T \log V)\)\(T\) 含义同上。

[CF1399F] Yet Another Segments Subset/洛谷/CF

2300 difficulty/INF/1 submit

感觉很套路,为什么不会呢?数据结构优化 DP。先离散化掉,记 \(f_i\) 表示考虑到第 \(i\) 条线段的答案是多少,为了方便统计可以多插入一条 \([0,INF]\) 的线段,最后答案即为它的 \(f - 1\)。要不重不漏的统计,先将线段按照右端点递增,左端点递减的顺序排序。转移方程为 \(f_{i} = \max_{l_i \leq l_j \wedge r_j \leq r_i} f_j + c_j\),其中 \(c\) 表示这条线段最多能够合法的覆盖多少条线段,求法和 \(f\) 类似,将已经得出的 \(f_k + c_k\) 放在 \(r_k\) 上,那么求新的 \(f_k\) 只需要在 \([1,l_k - 1]\) 上查询最大值。单点修改,区间查询可以线段树完成。于是可以做到 \(\mathcal O(n^2 \log n)\)

[CF1322C] Instant Noodles/洛谷/CF

2300 difficulty/INF/2 submit

想了一万年,急。首先有 \(\gcd(a,b) = \gcd(a,b,a+b)\)。取两个右部点 \(i,j\),记它们连接的左部点点集为 \(s_i\)\(s_j\)。如果 \(s_i \cap s_j = \emptyset\),那么直接直接 \(\gcd(c_i,c_j)\) 即可。如果 \(s_i = s_j\),那么左部点只要选到点集中的点,右部点的和一定是同时存在 \(c_i\)\(c_j\),因此答案形式一定是别的方案和 \(c_i + c_j\)\(\gcd\),因此合并 \(c_i\)\(c_j\) 即可。如果 \(s_i \cap c_j \neq \emptyset\),那么答案的形式会出现 \(\gcd(c_i,c_i + c_j),\gcd(c_j,c_i + c_j),\gcd(c_i,c_j,c_i + c_j)\) 三种,他们的结果都是 \(\gcd(c_i,c_j)\)。所以问题变成了对于右部点,合并连接左部点点集相同的点,然后对所有情况取 \(\gcd\),可以直接 map 套 set 实现映射,合并答案遍历 map 即可。这样做到 \(\mathcal O(n \log n)\)

[CF1294F] Three Paths on a Tree/洛谷/CF

2000 difficulty/18' times/3 submit

贪心。将答案视作一条链加上从这条链上延伸出一段路径,那么为了结果最大,先选的链一定尽可能长,所以先选掉直径。再找一个点还是贪心的选取距离最远的,暴力跳父亲标记直径上的点后再从直径上任意一点遍历一次,找最远的一个端点即可。需要注意的是如果是一条链,需要在链上随便选取一个点,防止答案不合法的问题。复杂度 \(\mathcal O(n)\)

[CF1027F] Session in BSU/洛谷/CF

2400 difficulty/27' times/2 submit

这个的强化版?先把时间离散化,对于每次挑选操作,相当于把两个时间所在的位置合并。如果一个连通块大小为 \(n\),合并了超过 \(n\) 次,那么无解;等于 \(n\) 次,则该连通块答案为块内最大的权值;等于 \(n - 1\) 次,答案为块内次大的权值。显然一个大小为 \(n\) 的连通块至少要合并 \(n - 1\) 次。按顺序操作后得到若干个连通块,分别求解后合并取最大的值即为答案。复杂度 \(\mathcal O(n \log n)\),瓶颈在离散化。

[CF946E] Largest Beautiful Number/洛谷/CF

2200 difficulty/19' times/1 submit

贪心。首先若能构造出长度相等的串,必然尽可能长,否则答案为少一位的一串 \(9\)。记当前构造出的串和原串的 LCP 为 \(s\),那么假如说考虑到第 \(i\) 位,当前会有两种选择:使第 \(i\) 位成为 LCP 的一部分,或者从这一位开始先将前面不能构成美丽数的数字补齐,再在末尾添一串 \(9\)。那么只需要枚举前缀长度,枚举间断位置选什么数字,让间断点严格小于原串中这一位。接下来统计构造的前缀中需要补那些数字才能使得新串合法,添加后再补 \(9\) 即可。需要注意的是不能有前导零,所以枚举时对于第一位字符集不能枚举到 \(0\)。于是做到 \(\mathcal O(\sigma n)\),其中 \(\sigma\) 是字符集大小,本题中为数字集,即 \(\sigma = 10\)

[CF1830B] The BOSS Can Count Pairs/洛谷/CF

2000 difficulty/21' times/1 submit

值域和数量同阶,乘法是个好东西,注意到有用的 \(a\) 最多就到 \(\sqrt{2 \times n}\),记 \(a_i < a_j\),枚举一个 \(x\),对于 \(a_i = x\) 在桶里面存 \(b_i\),然后遍历序列找 \(x \times a_j - b_j\) 的个数即可。这样做到 \(\mathcal O(n \sqrt{n})\)

[CF1220E] Tourism/洛谷/CF

2200 difficulty/INF/3 submit

环是可以随便乱走的,最终答案一定是形如走了一堆以可以返回的点为终点的路径加上一条走到死路的路径。先缩边双,注意到如果边双大小超过了 \(3\),那么这个连通块就具备能够往回走的能力。缩完边双后得到若干棵树,只考虑包含起点的连通块所在的那一棵,考虑以其为根做树形 DP,设 \(f_i\) 表示不能返回的走,\(i\) 子树得到的最大权值和;\(g_i\) 表示能够返回的走,\(i\) 子树得到的最大权值和。答案即为 \(g_s\)。能够返回走的能力也具备传递性,一个连通块如果能够返回走,那么在树形态上它的祖先节点都将具备这个能力,于是再记一个 \(c_i\) 表示 \(i\) 节点是否具有往回走的能力,边界为 \(c_i = [siz_i \geq 3]\),转移为 \(c_i |= \sum_{j \in son_i} c_j\)。自然就能得到 \(f\) 的式子:\(f_i = \sum_{j \in son_i \wedge c_j } f_j\)\(g_i = \max_{j \in son_i} g_j + f_i - [c_i == 1]f_j\),要减去是因为如果儿子具备返回的能力,那么 \(f_i\) 已经将 \(f_j\) 的值统计过,会重复计算贡献。于是三遍 dfs 做到了 \(\mathcal O(n)\)

[CF228E] The Road to Berland is Paved With Good Intentions/洛谷/CF

1900 difficulty/19' times/1 submit

一个点只会操作 \(0\)\(1\) 次,反复操作是无效的。如果一条边是 \(0\),那么需要操作两个端点中的一个恰好一次;如果一条边是 \(1\),那么需要两个端点都操作或都不操作。使节点有两种取值 \(0\)\(1\) 表示操作或不操作,这是经典的 2-SAT 问题,按上述描述连边即可,前者有 \(\neg x \wedge y\)\(x \wedge \neg y\),后者有 \(x \wedge y\)\(\neg x \wedge \neg y\)。于是做到 \(\mathcal O(n + m)\)

[CF1879D] Sum of XOR Functions/洛谷/CF

1700 difficulty/33' times/2 submit

乘法对异或没有分配律,但是拆位之后对若干个二次幂的和就有分配律了。先前缀异或和,然后就化成了 \(\sum_{l = 1}^{n} \sum_{r = l}^{n} (s{l - 1} \oplus s_r) \times (r - l + 1)\),对于一个区间异或能够有贡献,当且仅当前缀和上 \(s_{l - 1}\)\(s_{r}\) 两个数在这一位上不相同。对于每一位从左到右扫一遍,维护当前前面在这一位上有几个 \(0\)\(1\),这样就能累加出前面所有 \(0\) 或者 \(1\) 距离这一位的总距离,乘起来对于每一位再累加即可。于是做到 \(\mathcal O(n \log V)\)

[CF1624F] Interacdive Problem/洛谷/CF

2000 difficulty/22' times/3 submit

一眼 \(2^{10} > 1000\),往二分上考虑。如果每次询问不会改变初始 \(x\) 的值,那么就是找到恰好的 \(x + y = n\),这个可以判断 \(\lfloor \dfrac{x + y}{n} \rfloor\) 是否为 \(1\) 来简单得到,如果为 \(1\) 则说明 \(x \leq n - y\),不妨二分 \(m = n - y\)。假设初始值为 \(x'\),现在的值为 \(x\),当前二分出一个 \(y\),依旧取 \(m = n - y\),如果交互返回值 \(\lfloor \dfrac{x + m}{n} \rfloor = k,\lfloor \dfrac{x}{n} \rfloor = k + 1\),此时仍能够判断 \(x\)\(m\) 的大小关系。记 \(x = x' + s\),这个 \(s\) 可以通过累积的询问确定下来。于是要让 \(m + s + y = (k + 1) \times n\),此时答案为 \(x' + s\),为了使 \(1 \leq m < n\),所以令 \(m = (-(s + y)) \% n\)。查询次数是 \(\log n\) 的。

[CF1624G] MinOr Tree/洛谷/CF

1900 difficulty/16' times/1 submit

先拆位,从高向低位考虑尽可能选零即可。先将这一位边权是 \(0\)未被标记的边拉出来,看是否能够组成一棵生成树(这部分 Kruskal 即可),如果可以说明不需要使用这一位为 \(1\) 的边权,将后者全部标记,因为以后也不能使用这些边。最后在遍历一遍看用掉了哪些边,统计答案即可。复杂度是 \(\mathcal O((n + m) \log V)\) 的。

[CF703D] Mishka and Interesting sum/洛谷/CF

2100 difficulty/39' times/1 submit

一眼丁真,鉴定为 HH的项链。首先补集转化一下,变成求 \([l,r]\) 中不重复出现的数的异或和异或上所有出现过的数的异或和。对于后者通过前缀异或和简单实现。对于后者等价于区间数颜色,先离线询问,然后按右端点排序。从左往右扫,加入一个数就在上一个该值出现的位置消除贡献。查询即为区间异或和。用异或运算的树状数组可以做到 \(\mathcal O(n \log n)\)。不过莫队也挺一眼的,直接离散化开桶维护每种数出现次数即可,不过是不是要劲爆卡常啊,感觉很不牛。

[CF490F] Treeland Tour/洛谷/CF

2200 difficulty/76' times/2 submit

先离散化掉。考虑答案一定是选择一个中间点为根,然后一段 LIS 的根链拼上一段 LDS 的根链,当然其中可能有一者长度为 \(0\),所以要维护对于每个节点,它子树中最长的 LIS 链和最长的 LDS 链。对于每个节点建一棵权值线段树, 那么线段树上位置 \(i\) 表示以值 \(i\) 结尾的最长的 LIS/LDS 长度,更新节点就是做一个线段树合并的过程。处理完一棵子树后要更新以其为端点的最长 LIS/LDS 长度,于是做到 \(\mathcal O(n \log n)\)

[CF1548B] Integers Have Friends/洛谷/CF

1800 difficulty/27' times/3 submit

若区间所有数同余,则对于任意 \(a_i = k_i m + x\),做一遍差分之后就有 \(s_i = (k_i - k_{i - 1}) m\),然后问题转化成寻找最大的子区间使得区间 GCD 大于 \(1\)。建立 ST 表,然后对于每个左端点二分找右端点即可,复杂度做到 \(\mathcal O(n \log^2 n)\)

[CF1821E] Rearrange Brackets/洛谷/CF

2100 difficulty/24' times/1 submit

有用的操作是将 ((())) 拆成 (()()),然后从里向外从右向左以此消括号代价是最小的。将原括号串建出括号树,初始给定的括号串一定合法,建一个一号节点为虚根,显然共有 \(\dfrac{n}{2} + 1\) 个节点,能够发现答案是 \(\sum_{i = 2}^{\frac{n}{2} + 1} (siz_i - 1)\)。那么操作就转化为把一个点的子孙交给父亲,即操作第 \(i\) 个节点会使答案减小 \(siz_i - 1\),所以操作每个节点的顺序是无关紧要的。先计算完不操作的答案,之后贪心的选前 \(k\) 大即可。桶排可以复杂度 \(\mathcal O(n)\)

[CF1579G] Minimal Coverage/洛谷/CF

2200 difficulty/52' times/5 submit

首先答案肯定具有单调性,因为小长度能够做到,大长度也一定能做到。同时注意到如果一个负数位置作为了一种合法位置的结束点,那么所有线段放置取反就可以得到其绝对值位置作为结束点。二分答案,发现值域和个数都不是很大,考虑直接维护这个东西进行 check。\(f_{i,j}\) 表示当前考虑到第 \(i\) 条线段,位置 \(j\) 能否成为结尾位置,这个 DP 的妙点在于仅仅考虑了 \(j\) 能否成为第 \(i\) 条线段的结尾位置,即第 \(i + 1\) 条线段的起始位置,而并没有考虑前 \(i\) 条线段能否真正的放下,所以第一条线段“可能”可以放在任何起始点,即 \(0\) 到二分出来的值都可以作为起始点。转移考虑每个结尾在合法位置\(j\),都能够转移到合法位置 \(j \pm d\),这里的合法指的是结尾位置不超过当前二分出来的答案,所以 \(f_{i,j} = f_{i-1,j-d} \vee f_{i-1,j+d}\)。这是个可行性 DP,只有 \(01\) 两种取值,并且转移还是区间平移,直接 bitset 优化,第一维可以滚掉,复杂度 \(\mathcal O(\dfrac{nV \log V}{w})\)

[CF708C] Centroids/洛谷/CF

2300 difficulty/69' times/3 submit

根据重心的定义,\(n\) 个点的树根节点任意子树大小不能超过 \(\lfloor \dfrac{n}{2} \rfloor\),将符合如上条件的子树称为合法。假设一个节点不能作为重心,说明它存在一棵大小超过 \(\lfloor \dfrac{n}{2} \rfloor\) 的子树。题目给定的操作形如选中一棵子树断开并连到新的位置。那么考虑到 \(i\) 号节点时,若想 \(i\) 成为重心,必然是将以 \(i\) 为根的条件下最大的合法子树拿出来接在 \(i\) 上。问题转化成找以 \(i\) 为根时最大的合法子树。这种东西看上去就很换根。首先可以一遍求出以 \(1\) 为根时每个节点的最大合法子树,那么换根到 \(i\) 时最大合法子树有三种决策,一种是以 \(1\) 为根时它向下的部分,一种是以 \(1\) 为根时它的父亲的其它儿子,一种是以 \(1\) 为根时它的父亲砍除和它的爷爷之间的连边后它的爷爷所处的连通块。后两者实际计算时都要带上 \(i\) 的父亲。记 \(f_{i,0/1}\) 表示以 \(1\) 为根时节点 \(i\) 的最大/次大合法子树,因为第二种转移需要考虑 \(v\)\(v\) 的父亲 \(u\)\(f_{u,0}\) 的转移点,所以需要记录次大,第一遍 dfs 可以 DP 出这个数组以及记录每个节点的重儿子。再第二遍 dfs 记 \(g_{i}\) 表示子树外能移除的最大合法子树,如果 \(v\)\(u\)\(f_{u,0}\) 决策点,那么 \(g_{v}\) 就可取值 \(f_{u,1}\),否则是 \(f_{u,0}\),自然如果 \(n - siz_u\) 即第三种转移是合法的话也可进行。第二遍 dfs 的时候同时判节点是否合法,具体而言是以 \(1\) 为根时节点的上下两部分是否出现不合法,显然若有不合法最多只会有一边,然后看移除相应的部分的最大合法子树能否合法即可。

[CF985E] Pencils and Boxes/洛谷/CF

2100 difficulty/23' times/2 submit

首先肯定是大小相近的在一个组,所以从小到大排序后每个分组是一个连续的区间。考虑做一个可行性 DP,\(f_i\) 表示当前考虑到第 \(i\) 个位置能不能以其合法结尾,那么对于 \(f_j (j \geq i + k - 1 \wedge a_j \leq a_i + d)\) 都能由合法的 \(f_i\) 转移而来,边界自然是 \(f_0 = 0\),如果 \(f_n\) 合法则说明有解,如果还要输出分组方案再纪录一个由谁转移而来即可。因为由一个位置转移而来就不用再管了,所以注意到右端点是单调不减的,因此单指针就做到 \(\mathcal O(n)\) 了。

[CF327E] Axis Walking/洛谷/CF

2100 difficulty/45' times/3 submit

我是弱智,越界调了一年。看到这个数据范围一般不是搜就是状压,直接 \(f_S\) 表示当前使用了 \(S\) 这些牌,再辅助的记一个 \(g_S\) 表示使用了 \(S\) 这些牌当前是什么位置,那么如果有 \(d_S = b\) 就不转移了。转移直接枚举上一张牌使用的是什么,这样用枚举 lowbit 就能很好的解决。综上,复杂度为 \(\mathcal O(2^n \log n)\)

[CF1473E] Minimum Path/洛谷/CF

2400 difficulty/28' times/1 submit

将式子转化成一条边免费,一条边花费双倍距离,能够发现实质上做的就是找这种限制下 \(1\) 到每个节点的最短路。记 \(dis_{i,0/1,0/1}\) 表示当前在节点 \(i\),是否用过免费边,是否用过双倍距离边的最短路是多少,那么答案就是 \(dis_{i,1,1}\)。直接分类讨论跑 dijkstra 即可。需要注意的是对于一条边它可以同时即是免费边又是双倍距离边,这样就是正常的距离。可能这也是一种分层图的变式,复杂度 \(\mathcal O(m \log n)\),应该有一个 \(4\) 的常数。

[CF988F] Rain and Umbrellas/洛谷/CF

2100 difficulty/INF/1 submit

vp 摆了,这么板的没做出来。数据范围直接考虑 \(\mathcal O(n^2)\)。首先任何时刻人肯定只拿一把伞,所以设 \(f_{i,j}\) 表示当前在位置 \(i\),身上带着第 \(j\) 把伞的最小代价,\(f_{i,0}\) 表示没伞。任意位置只会进行三种决策:

  • 扔伞(要求 \(i\) 位置不下雨)。
  • 换/拿伞(要求 \(i - 1\) 位置上有伞)。
  • 撑伞走(要求在 \(i - 1\) 手上有伞)。

按照题意模拟即可,对于同一位置上的多把伞,肯定贪心要重量最小的,时空都做到 \(\mathcal O(n^2)\)

[CF1878F] Vasilije Loves Number Theory/洛谷/CF

1900 difficulty/45' times/2 submit

solution

[CF1834D] Survey in Class/洛谷/CF

1900 difficulty/27' times/1 submit

找到一对线段,最大化 \(|a \setminus a \cap b|\)。分类讨论:如果 \(b \subseteq a\),那么答案为 \((a_{r} - a_{l}) - (b_{r} - b_{l})\);如果 $ a_{l} \leq b_{r} \leq a_{r}$,答案为 \(a_{r} - b_{r}\),按右端点排序做;如果 \(a_{l} \leq b_{l} \leq a_{r}\),答案为 \(b_{l} - a_{l}\),按左端点排序做。三者取最大值即可,瓶颈在于排序,复杂度 \(\mathcal O(n \log n)\),不过应该容易 \(\mathcal O(n)\)

[CF1842D] Tenzing and His Animal Friends/洛谷/CF

1900 difficulty/19' times/1 submit

很有意思的最短路。u 和 v 中只有一个在聚会中的总时间不超过 \(w\),建双向边 \((u,v,w)\) 表示 \(u\)\(v\) 或是 \(v\)\(u\) 单独在聚会中的时间要多 \(w\),有一点像差分约束的感觉。因为 \(n\) 不能参加任何一个聚会,所以考虑从 \(n\) 开始跑最短路,那么每个人可以参加的最长聚会时间就是从 \(n\) 到该点的最短路。如果 \(1\)\(n\) 不连通,\(1\) 就可以一直聚会从而输出 inf,否则最大聚会时间就是从 \(n\)\(1\) 的最短路。构造方案考虑根据最短路来构造,记 \(n\) 到点 \(i\) 的最短路距离为 \(d_i\),每次找到全局最小的 \(d_i\) 即为当次聚会时间 \(t\),然后当前局面下 \(d_i\) 还有值的参加聚会,再给所有有值的 \(d_i\) 减掉 \(t\),重复上述过程直至 \(d_1 = 0\),暴力枚举完成这个过程即可。复杂度 \(\mathcal O(m \log n + n^2)\),比较轻松跑过。

[CF475D] CGCDSSQ/洛谷/CF

2000 difficulty/17' times/1 submit

套路题,gcd 只会变化 log 次,枚举左端点,二分右端点在哪些位置会变化并拿 map 记录答案,check 拿 ST 表维护即可,这样就做到了 \(\mathcal O(n \log n)\)

[CF1888D] Dances/洛谷/CF

1900 difficulty/INF/1 submit

赛时弱智了。首先 easy version 的话就 A 和 B 都从小到大排序,然后肯定是贪心的 A 删除大的,B 删除小的,枚举两个序列是如何对应上的,可以做到 \(\mathcal O(n \log n)\)。然后考虑 hard version,注意到随着 \(a_1\) 增大,重新排序 \(a\) 之后如果 \(a_1\) 的位置没有改变,那么答案不变,否则直接再删掉 \(a_1\),所以答案最多变小 \(1\),然后就可以二分出 \(a_1\) 取到什么值答案会变劣,剩下过程同 easy version,复杂度 \(\mathcal O(n \log n \log m)\)

[CF1888E] Time Travel/洛谷/CF

1900 difficulty/25' times/1 submit

刚学的东西用上场切了。solution

[CF1895D] XOR Construction/洛谷/CF

1900 difficulty/17' times/1 submit

把条件化一下,记个转换量,得到 \(a_1 \oplus a_{p + 1} = \oplus_{i = 1}^{p} b_i = s_p\),对 \(b\) 做一遍异或前缀和即为 \(s\),所以 \(a_{p + 1} = s_p \oplus a_1\),现在问题在于如何求 \(a_1\)。注意题目保证了一定有解,并且是一个 \(0 \sim n - 1\) 的排列,这也就是说 \(a_1\) 和所有 \(s\) 的异或和尽可能小。按位考虑,如果 \(s\) 在这一位上 \(1\) 的数量超过了一半,那么 \(a_1\) 在这一位上取 \(0\),否则取 \(1\) 即可。复杂度 \(\mathcal O(n \log V)\)

[CF1242B] 0-1 MST/洛谷/CF

1900 difficulty/INF/1 submit

怎么感觉这么困难呢,鉴定为不会证明复杂度导致的/fn。首先第一步,根据 kruskal 肯定先尽可能选 \(0\) 边再选 \(1\) 边,选 \(0\) 边的过程就是找出反图的若干连通块,于是将问题转化成了求反图连通块数量。因为正图边数量很少,先找出正图中度数最小的那个点,然后将反图上和它联通的点并查集合并掉。遍历反图的出边可以存正图的出边后将点的编号从小到大排序,然后 \(\mathcal O(n)\) 的单指针模拟。根据鸽巢原理,这个点的度数不会超过 \(\dfrac{2m}{n}\),因此这一步操作完之后剩下的连通块个数不会超过\(\lceil \dfrac{2m}{n} \rceil\) 个,再暴力合并就好了,复杂度 \(\mathcal O((\min \{ \dfrac{2m}{n} , n \})^2)\),注意到 \(\min\) 里头的两项乘积为 \(2m\) 即这个东西的值不会超过 \(\sqrt{2m}\),因此复杂度实际上是 \(\mathcal O(n + m)\) 的。

[CF1876C] Autosynthesis/洛谷/CF

2100 difficulty/INF/5 submit

赛时没切,太菜了。题意等价于将序列划分为两部分,使得一部分的下标序列等于另一部分的值序列。将 \(i\)\(a_i\) 连边得到一个内向基环树森林,将位于下标序列的节点称为 \(A\) 类,值序列的称为 \(B\) 类,观察到一个节点作为 \(A\),当且仅当它有一个儿子为 \(B\);一个节点是 \(B\),那么它的父亲一定是 \(A\);叶子结点一定是 \(B\)。根据上面的信息,树的部分就类似于交替染色,这个可以拓扑排序做,然后图里面就剩下了若干个环。如果一个环上没确定的 \(A\) 类点,那么还是长度为偶数交替染色,奇数无解。若环上已经有了如果 \(i\)\(B\)\(a_i\) 未被确定,那么 \(a_i\)\(A\),否则不合法;如果 \(i\)\(A\)\(a_i\)\(A\),则说明 \(a_i\) 在树上有个儿子是 \(B\),否则 \(a_i\) 未被确定,选 \(a_i\)\(B\) 即可。这样就做到 \(\mathcal O(n)\) 了。

[CF1801C] Music Festival/洛谷/CF

1900 difficulty/39' times/1 submit

对于一个段的内部,先求出段内最大值,然后预处理出若干个三元组形如 \((l,r,v)\) 表示到位置 \(l\) 该段的严格上升子序列长度为 \(v\)\(r\) 则为段内最大值,表示放下这个段之后再有贡献就要大于这个值了。这个可以用单调栈线性做,显然有贡献的位置只可能是前缀最大值。然后将这些三元组按 \(l\) 递增排序,记 \(f_i\) 表示考虑到第 \(i\) 个三元组答案最大是多少,转移就形如 \(f_{i} = \max_{j = 1 \wedge r_j < l_i}^{i} \{ f_j \} + v_i\),发现决策点是值域上的一段前缀,于是就可以树状数组优化 DP 了。复杂度 \(\mathcal O(n \log n)\),删除不能 memset,否则复杂度不对。

[CF1801D] The way home/洛谷/CF

2100 difficulty/27' times/2 submit

如果钱不够了,肯定是贪心的在赚钱最多的城市表演,所以如果想走一条路钱不够了,就提前在经过的城市中能赚最多钱的那个城市把钱赚够,所以自然的扩出一维状态。\(f_{i,j}\) 表示当前在城市 \(i\),经过的赚钱最多的城市是 \(j\) 的最少演出次数,同时要伴随着记一个 \(g_{i,j}\) 表示在满足最少演出的前提下剩的钱最多是多少,然后类 dijkstra 优化 DP 转移即可,这样做到 \(\mathcal O(m \log n^2)\)

posted @ 2023-07-31 21:32  LgxTpre  阅读(99)  评论(0编辑  收藏  举报