CF思维题做题记录-1

CF2600左右有趣的思维题做题记录-1

CF1458C. Latin Square

考虑将原矩阵写成 \(n\times n\) 个限制形如 \((i,j,a_{i,j})\),那么所有操作就是对这些限制进行的修改:

  • 对于 UD 操作相当于将限制改为 \((i\mp 1,j,a_{i,j})\)
  • 对于 LR 操作相当于将限制改为 \((i,j\mp 1,a_{i,j})\)
  • 对于 IC 操作相当于将限制改为 \((i,a_{i,j},j)\)\((a_{i,j},j,i)\)

因此可以看出我们只需要维护在所有操作结束后三元组的变化情况(包括每一维最后所处的位置和其对应的偏移量)就可以快速得出操作后的矩阵,那么复杂度可以做到 \(O(n^2+m)\)

CF1666E. Even Split

关注到一个较大的极差中肯定可以构造一个较小极差的方案,也就是说极差是具有单调性的,可以考虑二分。

二分出一个极差后,我们考虑如何判断这个极差是否合法。显然光有极差是难以判断的,我们还需要最小值和最大值。考虑已知最小值和最大值 \(L,R\) 后如何去判断是否有解:对于每一个 \(a_i\),我们显然可以计算出包含这个点的区间的可行右端点范围 \([l_i,r_i]\),因为有

\[l_i=\max(l_{i-1}+L,a_{i}),r_i=\min(r_{i-1}+R,a_{i+1}) \]

那么显然我们还要求 \(l_i\le a_{i+1},r_i\ge a_i\),否则我们显然无法构造出合法的解(我们认为 \(a_{n+1}=l\))。显然这两个条件不可能同时不成立,并且我们可以分析出违反第一个条件是因为最小值太大了,违反第二个条件是因为最大值太小了,也就是最小值同样满足单调性,那么我们依旧可以通过二分简单求出是否存在一个合法的 \(L,R\) 并给出构造。

现在问题在给出方案,考虑先取所有 \(p_i=l_i\),那么 \(p_i-p_{i-1}\ge L\) 的条件就已经满足了,接着我们先强制要求 \(p_n=l\),接着从后往前推,令所有 \(p_i-p_{i-1}>R\)\(p_{i-1}\) 的值为 \(p_i-R\),这样也就满足了 \(p_i-p_{i-1}\le R\) 的条件。因为你已经保证了对于 \(L,R\) 有解,那么这样构造出来的方案定然是合法的。那么我们可以做到 \(O(n\log^2V)\) 的复杂度。

CF1809E. Two Tanks

考虑不管怎样倒水两个水桶里的水的总量不变,因此不妨将总量相同的点放在一起考虑。

在这种情况下,我们发现 \(v_i>0\) 相当于试图将所有点向右上方移动 \(v_i\) 步(一步指从 \((a,b)\) 移动到 \((a-1,b+1)\)),相应的 \(v_i<0\) 相当于试图将所有点向左下方移动 \(-v_i\) 步(一步指从 \((a,b)\) 移动到 \((a+1,b-1)\)),显然越界的操作我们不会执行。那么最靠左下的若干个点将会重叠在一起,最靠右上的若干个点将会重叠在一起,剩下的点相邻的分布在对应位置上,每个点的答案就是其所处位置的横坐标。

于是我们只需要知道对于每个不同的总量,在操作完之后有多少个最靠左下的点重叠在了一起、有多少个最靠右上的点重叠在了一起、最左下的点在操作完之后相对于初始位置移动了多少步就可以推出所有点的答案。

事实上注意到对 \(v\) 求出前缀和 \(v'\),记 \(L=1+\max\limits_{i=0}^{n}-v'_i,R=1+\max\limits_{i=0}^{n}v'_i\),那么前 \(L\) 个最靠左下的点和前 \(R\) 个最靠右上的点是一定会重叠在一起的,因此只需要统计最左下的点在操作完之后相对于初始位置移动了多少步就可以了。复杂度是 \(O(n(a+b))\) 的。

CF1774F2. Magician and Pigs (Hard Version)

我们设 \(w_i\) 表示第 \(i\) 次操作 3 之前的所有操作造成的减少的和,对于 \(w\) 的维护是容易的:对于操作 2\(w\) 会加上减少的生命 \(x\);对于操作 3\(w\) 会翻倍。

那么对于这次操作之前的所有操作 1 产生的当前生命为 \(x\) 的猪,相当于要选择变成 \(x\) 还是 \(x-w\)(考虑这头猪在复制后是前面的还是后面的),那么要求的内容就是 \(x\) 在减去之后的所有 \(2\) 操作后,有多少种选择方法能够使最终的 \(x>0\)

注意到我们有 \(2w_i\le w_{i+1}\),也就是除去最开始的 \(w_i=0\) 的操作 3,我们最多有 \(\log V\) 个操作 3 是有效的,否则我们定然不能让 \(x\) 减去 \(w\)。然后考虑如何统计方案数,除了有效的操作 3 的数量,\(2w_i\le w_{i+1}\) 还保证了 \(\sum\limits_{k=1}^{i}w_i<w_{i+1}\)。那么我们只需要从大到小枚举 \(w\),如果当前的 \(x\) 足够减去这个 \(w\),就说明如果不减这个 \(w\),后面的选择可以任意选,贡献是 \(2^{i-1}\)。然后我们只剩下一种选择,向下继续枚举即可。复杂度是 \(O(n\log v)\) 的。

CF1208G. Polygons

考虑在选择一个 \(n\) 之前,我们肯定已经选择了其的所有因子。如果存在某个因子 \(d\) 还没有选,那么因为我们一定可以调整使得这 \(d\) 个点被 \(n\) 个点完全包含,那么选择 \(d\) 肯定不劣。

现在 \(n\) 的所有因子已经选过了,我们记所有多边形都存在一个点 \(0\),那么其它的点顺次排开应该是 \(\frac{1}{n},\frac{2}{n},\cdots,\frac{n-1}{n}\),能够留下的点一定满足分子分母互质,否则选择两个数的最大质因子时这个点一定已经出现了。那么一个边数为 \(n\) 的多边形的贡献就是 \(\varphi(n)\),用线性筛求出后,排序选择前 \(k\) 小的值即可。

然而,因为我们只能选择 \(n\ge 3\) 的多边形,那么实际上我们并没有统计到 \(0,\frac{1}{2}\) 这两个点,那么我们求得的答案就是错的。不妨考虑特判:

  • \(k=1\) 时我们一定选择正三边形,此时应该统计 \(0\) 这个点。
  • \(k=2\) 时我们一定多选择了正四边形,此时应该统计 \(\frac{1}{2}\) 这个点。
  • \(k\ge 3\) 时两个点都已经在选择正三边形和正四边形的时候统计了,不需要继续特判。

于是我们只需要特判 \(k=1,2\) 的情况。复杂度瓶颈在排序的 \(O(n\log n)\)

CF1887C. Minimum Array

考虑对操作差分,那么当差分数组的第一个非 \(0\)\(<0\) 时,当前数组的字典序一定比之前记录的字典序要小,那么我们记录此时的数组,然后清空差分数组即可。关注到我们只需要清空有值的位置,那么复杂度是正确的,用线段树可以简单维护这个内容,复杂度是 \(O(n\log n)\) 的。

CF1672F2. Checker for Array Shuffling

考虑排列的交换次数越多,那么排列所形成的置换环个数就越少。考虑对给定的原序列构造一个置换环,显然如果一个置换环中存在相同元素,我们肯定存在一个方案使得环更多,因此最终得到的环中肯定不存在相同的元素。那么不难构造出环的个数为 \(\max c_i\) 满足条件(其中 \(c_i\) 表示 \(i\) 的出现次数)。

考虑如何判定。不难发现不存在一个环使得其中没有出现次数最多的元素是环的个数是 \(\max c_i\) 的充要条件。那么考虑对于一个 \(i\),所有 \(a_p=a_i\)\(p\) 向所有 \(b_q=b_i\)\(q\) 连边,最后删除所有出现次数最多的元素,如果仍然存在环则不合法。直接连边有 \(O(n^2)\) 条边,建立虚拟节点可以做到 \(O(n)\)。用拓扑排序判环,复杂度可以做到 \(O(n)\)

注意有多个出现次数最多的元素时我们只取其中之一。

CF1975F. Set

考虑到当我们确定一个元素是否在集合中时,我们本质需要的限制会减半,因此可以直接搜索。每次确定一位 \(i\) 后,先判断 \(V_{f(\{i\})}\) 是否合法,然后将 \(V_{f(S)}\)\(V_{f(S\cap\{i\})}\) 的限制合并,然后递归子问题即可。复杂度是 \(O(n\log n)\) 的。

CF1680D. Dog Walking

先特判掉无解的 corner case。接下来问题相当于要最大化极差,考虑极差相当于一段区间和,那么我们枚举这个区间,并试图让这个区间的和最大即可。显然我们为了最大化区间和,这个区间中的所有 \(0\) 要么全取 \(+k\),要么全取 \(-k\)

然而这个题目还限制了所有 \(a_i\) 的和必须为 \(0\),所以我们必须要求区间外的数可以平衡我们的最大值。设我们有不等式 \(L\le p\le R,L'\le p'\le R'\),为了使 \(p+p'=0\),我们有 \(\max(L,-R')\le p\le \min(R,-L')\)\(|p|\) 的最大值显然在端点处取到,于是我们可以做到 \(O(n^2)\) 求解。

CF1930F. Maximize the Difference

考虑所求本质相当于 \(\max\{(b_i|x)-(b_j|x)\}\)。考虑对于一对 \((i,j)\),如果数位上分别是 \((1,0)\),那么这一位肯定不能或 \(1\);而如果数位上分别是 \((0,1)\),那么这一位肯定要或 \(1\);对于 \((0,0)(1,1)\),这一位或不或都行,那么显然 \(x=b_j\) 时最优,那么就相当于求 \(\max\{(b_i|b_j)-b_j\}=\max\{b_i\&(\lnot b_j)\}\)

考虑如何动态维护这个内容,我们设 \(f_S\) 表示是否存在 \(S\subseteq b_i\)\(g_S\) 表示是否存在 \(S\subseteq (\lnot b_j)\),那么答案就是最大的使 \(f_S,g_S\) 同时成立的 \(S\)。我们考虑直接记忆化搜索更新 \(f,g\) 数组,复杂度均摊是 \(O(n\log n)\) 的。

CF1375G. Tree Modification

看到相邻考虑黑白染色,那么对于一个白色点操作相当于将其周围的所有黑色点挂到某一个白点上,并将这个点染为黑色后同样挂到白点上(对黑色点操作则正相反)。最后的形态显然只有一个黑色点或白色点,而每次最多减少一个黑色点或白色点,答案自然就是黑色点数量和白色点数量的最小值最后减去 \(1\),复杂度是 \(O(n)\) 的。

CF1817C. Similar Polynomials

对于一次函数我们显然是能快速求解的:设 \(A(x)=kx+b\),则 \(A(0)=b,A(1)=k+b,B(0)=A(s)=ks+b\),那么可以解出 \(s=\frac{B(0)-A(0)}{A(1)-A(0)}\)

然而现在我们有一个多次函数,因此可以考虑对函数降次,也就是差分。我们知道差分一次会让得到的函数的次数减 \(1\),那么只需要进行 \(d-1\) 次差分就可以得到一个一次函数,用 \(A(0),A(1),B(0)\) 计算 \(s\) 即可。至于如何快速计算 \(d-1\) 阶差分后的结果,我们有公式

\[\Delta^kf(x)=\sum_{i=0}^{k}\binom{k}{i}(-1)^{k-i}f(x+i) \]

于是可以在 \(O(d)\) 的复杂度内求解原问题。

CF1842F. Tenzing and Tree

考虑求出每个子树中黑点的个数 \(\text{sum}_i\),那么答案就是 \(\sum|k-2\text{sum}_i|\)。当我们以所有黑点的重心为根时,显然有 \(2\text{sum}_i\le k\),那么就可以去掉绝对值。考虑枚举这个重心 \(p\),那么所有的贡献就是 \(\sum(k-2\text{sum}_i)=(n-1)k-2\sum\text{dep}_i\),可以看出只需要最小化所有黑点的 \(\text{dep}\) 和即可,排序后贪心选择前 \(k\) 小的黑点即可,复杂度是 \(O(n^2\log n)\) 的。

如果我们贪心选出来的 \(k\) 个点不以 \(p\) 为重心,那么答案显然更小,因此不会有问题。

CF1369E. DeadLee

设当前第 \(i\) 道菜还有 \(c_i\) 个人要吃,还剩 \(w_i\) 个这道菜,那么当 \(c_i\le w_i\) 时显然这 \(c_i\) 个人肯定都有饭吃,那么不如把他们全部安排到序列尽可能后的位置,否则他们会抢占其他人的名额。然后我们将这些人除去后更新一下 \(c_i\),如果出现新的 \(c_i\le w_i\),就继续更新,这样操作直到无法更新。此时如果所有人都被安排了,那么输出即可;否则,对于此时所有的 \(c_i>w_i\),显然不论怎样安排顺序都不会使得 \(c_i\le w_i\),那么当所有 \(w_i=0\) 时,一定存在 \(c_i\) 不为 \(0\),显然不合法。

整个过程和拓扑排序较为相似,用队列实现即可做到 \(O(m)\)

CF1819D. Misha and Apples

考虑到最后有一段一直不会清空的集合,那么这段集合显然越长越好,因此我们考虑最早化最晚清空集合的位置。此时如果最后一段里存在可以任选的集合,那么最终答案肯定是 \(m\),否则答案就是所有集合大小相加。

考虑如何求这个位置。设 \(f_i\) 表示在 \(i\) 处是否可以清空集合,维护一个 \(p\) 表示在 \(i\) 之前的所求。考虑当前集合里出现的所有数字的最晚出现位置 \(p'\)

  • \(p'>p\),显然在 \(i\) 处可以清空,令 \(f_i=1\),并且此时的 \(p\) 已经不可能 \(<p'\) 了,因此先暂时\(p\) 赋值为 \(p'\)
  • \(p'\le p\),如果在 \((p,i]\) 这一段存在任选的集合,那么显然可以操控这个集合清空这一段,令 \(f_i=1\),此时不影响 \(p\)

考虑 \(p\) 所在的位置一定是一个可以清空的位置,因此让 \(p\) 不断自增直到 \(f_p=1\)。最后 \(p\) 即为所求,复杂度为 \(O(\sum n+\sum k)\)

注意题目不保证 \(\sum m\) 的范围,因此清空需要精细实现。

CF79D. Password

看到区间取反,自然想到对原数组进行差分,那么问题就转换成有 \(k(2\le k\le 20)\) 个位置为 \(1\),每次操作可以将相差为 \(a_i\) 的两个位置 \(p,q\) 取反,问最少操作数。

考虑将操作细分成若干个形如 \((u,p_1)(p_1,p_2)\cdots(p_{n-1},p_n)(p_n,v)\) 的形式,显然进行这些操作后只会有 \(u,v\) 两个位置被取反。这启发我们将所有在可以同时取反的位置之间连边,同时取反 \(p,q\) 的代价就是两个点之间的最短路。

直到所有点对之间的代价后,显然我们可以直接进行状压 dp,每次枚举新取反的两个节点,复杂度是 \(O(nk+4^{k})\) 的(这里的 \(k\) 是题目中的)。

注意直接差分对于前缀或后缀的操作会转化成只取反一个位置,因此需要加入 \(n+1\)\(0\) 一起差分。

CF1891E. Brukhovich and Exams

考虑一个贪心的思路,对于一个没有 \(1\) 的极长的互质连续段,设其长度为 \(l\),那么我们可以最多选择出 \(\lfloor\frac{l-1}{2}\rfloor\) 个位置,使得每次操作都能让互质对数减少 \(2\),显然我们总是优先操作这些位置。

接下来我们发现对于不在最开始和最结尾的极长的 \(1\) 的连续段,设其长度为 \(l\),当我们将其操作完后,我们将减少 \(l+1\) 对互质的数。这是因为这样的连续段两段一定有没有操作过的 \(>1\) 的数,显然我们第二步应该操作按 \(l\) 从小到大操作这些位置。

对于剩下的位置显然操作一个互质对数只能减少 \(1\),那么我们按次操作这些位置即可。

上述算法的总复杂度为 \(O(n\log n)\)

CF1886E. I Wanna be the Team Leader

考虑对 \(a\) 进行排序,那么一个任务就需要的人数就只取决于编号最小的人的能力值。显然我们总是让编号连续的人进行一个任务,否则定然不优。于是我们可以考虑 dp。

\(f_{i,S}\) 表示前 \(i\) 个人是否能完成任务集合 \(S\),转移考虑 \(i+1\) 是否在任意一个任务里:

  • 如果不在,那么转移到 \(f_{i+1,S}\)
  • 否则枚举没有完成的任务 \(k\),得到一个最小任务区间 \([i+1,R]\),转移到 \(f_{R,S\cup\{k\}}\)

这样可以做到 \(O(nm2^m)\) 的低劣复杂度。考虑因为第一种转移,对于每一个 \(S\),可行的前缀都是 \([x,n]\) 的一段后缀。于是可以考虑改设计为 \(f_S\) 表示能够完成任务 \(S\) 的最小的前缀,然而此时我们依旧需要枚举新任务的最小编号。

针对这个问题,我们可以算出 \(R_{i,j}\) 表示完成任务 \(i\) 的编号最小的人为 \(j\) 时所需的最大编号,\(L_{i,j}\) 表示完成任务 \(i\) 的编号最小的人的编号 \(k\ge j\) 时,所需最大编号最小的 \(k\),显然 \(L,R\) 可以在 \(O(nm)\) 的复杂度内求得。那么此时对于 \(f_S\),我们枚举新任务 \(k\),那么此时这个任务 \(k\) 的最优编号区间就是 \([L_{i,f_S+1},R_{i,L_{i,f_S+1}}]\),用右端点贡献到 \(f_{S\cup\{k\}}\) 即可,这样 dp 的复杂度就降到了 \(O(m2^m)\)

CF1799F. Halve or Subtract

首先将 \(a\) 从大到小排列,那么一定有一段前缀是同时进行操作 \(1,2\) 的,并且不难发现总是先除后减最优。设这一段的长度为 \(k\),那么应该有 \(\max(0,k_1+k_2-n)\le k\le \min(k_1,k_2)\),因为我们操作满肯定不劣。

现在只剩下 \(k_1'=k_1-k,k_2'=k_2-k\),并且剩下的元素我们一定只会进行一次操作,设 \(p\) 为最后一个 \(\ge b\) 的位置。从 \(k+1\)\(p\) 这段区间我们总是有一段前缀除,一段后缀减,因为此时谁减都无所谓,那么显然让大的除最优。从 \(p+1\)\(n\) 这段区间我们总是有一段前缀减,一段后缀除,因为此时除一定比减的贡献小,显然让大的减最优。总结一下,从 \(k+1\)\(n\) 这段区间我们总是一段除、一段减、一段除。因为减的段长度是确定的,只需要枚举减的这一段的开头就可以快速统计贡献了。

于是我们只需要枚举 \(k\) 和那段减的开头位置即可,复杂度是 \(O(n^2)\) 的。

CF1696F. Tree Recovery

考虑所有在树上的边在输入中一定有相等关系,即对于任意相邻的两条边 \((u,v)(v,w)\),我们一定能找到一个 \(s\) 中的 \(1\) 表示 \(d(u,v)=d(w,v)\)。并且这些边显然不和其他任意的边产生相等关系。那么按照相等关系将 \(O(n^2)\) 条边缩到一起,显然我们只想要大小恰为 \(n-1\) 的集合。

对于每一个集合,我们将其中的边对应的图建出来,显然这个图需要是一棵树且满足输入给出的限制。我们可以 \(O(n^2)\) 计算出任意两个点之间的距离后 \(O(n^3)\) 对所有限制进行判断。

对于大小恰为 \(n-1\) 的集合,最多有 \(n\) 个,因此总复杂度为 \(O(n^4)\)。然而在实际实现中,这样的集合个数可能接近 \(O(1)\),因此实际复杂度接近 \(O(n^3)\)

posted @ 2025-09-19 11:43  DycIsMyName  阅读(16)  评论(0)    收藏  举报