CF *2600 思维题 1
CF *2600 思维题 1
A CF1458C Latin Square
- trick 没见过,比较新颖。自己的考虑是从化简操作出发,但是失败了。
考虑将矩阵的每个元素看成一个三元组 \((i,j,a_{i,j})\),这样的话我们对于 RLDU 操作实际上就是对前两维中的某一位加一或减一。然后对于 I 操作,实际上就是交换三元组的第二维和第三维;对于 C 操作同理。
那么我们维护出三元组中每一维上加了多少,以及交换后第 \(i\) 维对应原来的第几维即可复原矩阵。复杂度 \(O(n^2+m)\)。
B CF1666E Even Split
- 第一个二分是容易的,但是
check里面再用二分没有快速想到。先假设变量已知的思路还是有用的。
首先看到极差最小肯定考虑二分,然后考虑怎么 check。注意到此时我们需要确定最小区间长度 \(l\) 和最大区间长度 \(r=l+mid\) 之后才能贪心放看是否可行。那么我们先假设已知了 \(l,r\),此时第 \(i\) 个区间与下一个区间的分割点 \(p_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,R_i]\) 我们也可以知道当前 \(l\) 是小了还是大了。所以我们可以直接通过二分来求出是否存在一个合法的 \(l\),然后就可以判断当前 \(mid\) 是否合法。
构造答案比较简单。复杂度 \(O(n\log^2 n)\)。
C CF1809E Two Tanks
- 观察有用的性质,注意按照条件分组求解。
首先发现两个水箱的水量总和保持不变,所以考虑对 \(c+d\) 相同的 \((c,d)\) 放在一起求解。
此时我们有 \(O(a)\) 个点,容易发现每一次操作就是将所有点向左 / 右挪动 \(v\) 个位置,并且将超出的部分全部放到端点上。那么在任意一个时刻,我们的点都一定在一段区间内,并且同一个位置上可能有多个点,这些点后续操作都是一致的。
那么考虑利用并查集进行维护,每一次枚举会被缩到一起的点,并查集合并即可。由于每一个点最多被合并一次,所以均摊复杂度是 \(O(a)\) 的。总复杂度是 \(O(na)\) 的,可以通过。
D CF1774F Magician and Pigs
- 发现了操作的性质,但是把倍增 \(\log V\) 次的结论忘了。
考虑复制操作的本质,假如当前我们总共打出的伤害为 \(s\),所有猪的集合为 \(P\)。那么复制操作的实质是将每个血量为 \(x\) 的猪复制出一个血量为 \(x-s\) 的猪,最后再将 \(s\) 乘二。
进一步发现,对于所有复制出来的猪,后续所有减血操作的影响是一致的,只有复制操作造成的血量变化不同。那么我们先将所有减血操作做完,然后再考虑复制操作。容易发现,复制操作的影响相当于从后面所有操作中选出一个子集,然后减去所有对应的 \(s\)。
所以我们现在需要求出有多少个子集的 \(s\) 之和小于当前血量。直接做复杂度肯定爆炸,不过考虑到每一次 \(s\) 至少乘二,所以 \(\log V\) 次操作后就不可能再选了,所以只需要对前 \(\log V\) 个数做背包即可。
这个背包也是有特殊性质的,因为我们发现第 \(i\) 个数是大于前 \(i-1\) 个数的和的。所以我们从大到小枚举,先排除 \(s\ge x\) 的情况。如果 \(s< x\) 且我们不选 \(s\),那么比 \(s\) 小的都可以选;否则的话我们让 \(x\) 减去 \(s\) 然后继续做即可。
这样的话做一次背包是 \(O(\log V)\) 的,总共要做 \(n\) 次,复杂度 \(O(n\log V)\)。实现的时候可以倒序枚举,这样更方便统计贡献。
注意有一种情况是 \(s=0\),此时只是单纯的复制了一次,记录系数即可。
E CF1208G Polygons
- 最后一步的性质没有发现。似乎结论中有欧拉函数的题我都很难发现。
首先考虑所有多边形一定共用一个端点,所以我们可以从这个端点出发考虑。进一步发现,对于一个边数为 \(k\) 的多边形,我们一定会选完 \(k\) 的因子再选他,不然一定不优。
现在我们考虑加入一个 \(k\) 会增加多少个点。我们考虑 \(k\) 边形会将圆分成 \(k\) 段,不妨编号为 \(\frac{i}{k}(0\le i<k)\)。容易发现,这里面有一些分数是可以化简的,这意味着之前已经有他的因子经过了这个点。所以他新加入的点就是所有满足 \(\gcd(i,k)=1\) 的点,显然就是 \(\varphi(k)\)。
所以我们预处理出所有 \(\varphi(i)\),取出前 \(k\) 小的即可。现在有一个问题是如何保证先选因子,容易想到的是因子的 \(\varphi\) 值一定更小,所以这个贪心是正确的。
时间复杂度 \(O(n\log n)\)。注意特判公共点,以及没有二边形。
F CF1887C Minimum Array
- 自己想的做法被卡常了,然后发现题解区有相同做法,结果也被卡了。。。
考虑在遍历的时候维护当前最小值,考虑从当前最小值到当前位置中间经过的所有操作。假设这些操作构成一个序列 \(b\),我们找出 \(b\) 中第一个非零位,如果这个位置 \(<0\) 则说明当前位置更优,更新答案并清空 \(b\) 即可。
现在我们要做的是区间加,找第一个非零位。其实比较困难,不过发现我们可以做一下差分,这样条件不变,并且变成了单点修改。用线段树直接维护即可,复杂度 \(O(n\log n)\)。
被卡常做法:
考虑翻转坐标系,每次我们只保留当前的最小值然后继续判断。容易发现每个位置最多被删除一次,这样总删除复杂度就是 \(O(q)\) 的。操作只有区间加,线段树维护即可,复杂度 \(O(q\log q)\)。
G CF1672F2 Checker for Array Shuffling
- 拼尽全力终于战胜。性质还是很巧妙的。
首先考虑求出一个改变后的序列的伤心度。考虑如果原序列是一个排列怎么做,很显然我们对于 \(b\) 序列连边 \(i\to b_i\) 数出置换环数量 \(cnt\),那么答案显然就是 \(n-cnt\)。
然后考虑本题,由于有重复元素,所以我们可以考虑给重复元素赋一个权值。但是此时对于 \(b\) 我们的赋权方式有很多,而我们要的伤心度是最小的操作次数,也就是要让 \(cnt\) 尽可能大。
考虑调整法构造,先乱给一个权值。发现如果一个置换环内有两个相同值的元素,我们可以交换它们的赋权,这样环就会被断开成两个,如此置换环个数就增加了。所以置换环个数一定大于等于出现次数最多的元素的出现次数。考虑题目中要求我们求伤心度最大的序列,也就是 \(cnt\) 尽可能大的情况下最小的序列。显然此时 \(cnt\) 应该等于出现次数最多元素的出现次数,并且容易发现这可以取到。
很显然要达成这一点,必须让每一个环中都有出现次数最多的那个元素,称其为 \(x\)。考虑建图,我们将一个 \(i\) 连向它所有可能连向的 \(j\),即所有满足 \(a_j=b_i\) 的 \(j\)。然后删去所有满足 \(a_i=x\) 的点。此时如果还有环,则说明我们有一种构造可以让一个环中没有 \(x\),此时就失败了。我们拓扑排序判环即可。
最后一个问题是我们边数是 \(O(n^2)\) 的,不过实际上我们可以用经典套路缩点缩成 \(O(n)\) 个,这样即可通过。
H CF1975F Set
- 我怎么看到二进制只会集合幂级数了???
- 这个题还是很唐的,没想出来主要还是没有往减少复杂度的目标走。
考虑我们枚举 \(S\) 的每一位是多少,如果这一位是 \(1\),那么意味着他会和同样在这一位上是 \(1\) 的 \(T\) 有贡献。不过我们如果把这个贡献加上去比较难处理。
考虑反过来,我们删去这一位上为 \(1\) 的 \(T\) 的这一位,此时我们剩下的部分的交必须属于某个 \(V\) 减一,那么将 \(V_T\) 右移并将 \(T\) 的这一位删去。然后我们会出现相等的 \(T\),显然他们两个的要求都要满足,所以取一个交即可。
复杂度是 \(O(n2^n)\),可以通过。
I CF1680D Dag Walking
- 终于在合理的时间里头写出来一个题了。
考虑到我们的行进路线一定形如 向右 - 向左 - 向右。第一次走到最大值,第二次走到最小值,最后一次走到 \(0\)。那么我们要求的实际上就是第二段行进的最大值。当然方向反过来也是可以的。
那么考虑枚举两个断点,将序列分成三段。每一段用前缀和可以求出他走的长度的最小值和最大值。然后简单算一下区间交的最大值即可。时间复杂度 \(O(n^2)\)。
J CF1930F Maximize the Difference
考虑我们取出两个数 \(a,b\) 做减法,那么如果这一位上对应数字是 \((1,0)\) 贡献就是 \(1\),如果是 \((1,1),(0,0)\) 贡献就是 \(0\),而如果是 \((0,1)\) 的话我们可以通过在这一位上或一个数让贡献变成 \(0\)。
于是可以看出,在题目中的 \(a,b\) 的贡献实际上就是 \(a\ \text{and}\ \text{not}\ b\)。考虑怎么求这个。我们加入一个数 \(v\) 的时候枚举 \(v\) 的子集,然后看前面有没有数是它的超集,并且我们也要同时将 \(v\) 对其子集的贡献加上。不过我们可以发现,当我们枚举到的这个子集已经被覆盖过了,我们就不用继续枚举这个子集的子集了。那么我们直接暴搜子集,每个数只会被覆盖一次,复杂度就是 \(O(n)\) 的。
对于 \(\text{not}\ a\) 也是同理。对于每个数我们要用 \(O(\log n)\) 的时间枚举它的下一个转移,所以总复杂度是 \(O(q+n\log n)\) 的,可以通过。
K CF1375G Tree Modification
- 小唐氏题,需要大力手玩。
先考虑固定一个根。很显然我们需要从下往上操作。考虑四个点 \(u,v,x,y\),满足 \(u\) 父亲为 \(v\),\(x,y\) 父亲为 \(u\)。此时如果想把所有点全部挂到 \(v\) 上,有两种操作方式:
- \((x,u,y)\) 和 \((y,u,v)\)。
- \((x,u,v)\) 和 \((y,u,v)\)。
这就告诉我们实际上我们不需要进行形如 \((x,u,y)\) 这样的操作,可以只进行向上的操作。而每一次我们会向上跳两条边,所以容易发现我们要操作的就是所有奇数层的点。当然还要减掉根的贡献。
换根的话也是容易的,不过有更简单的办法。考虑给这棵树进行黑白染色,那么奇数层的点一定全是黑点或者白点。所以输出较小值减一即可。方案应该也是容易的,不过没有要求。复杂度 \(O(n)\)。
L CF1817C Similar Polynomials
- 这个题还是有点超模,不知道为啥只有 2400。可能是我数学太差。
考虑到这个函数次数较高不好处理,我们能处理的最高的次数其实只有一次。考虑怎么降次,那么考虑求导,在点值意义下就是做差分。
我们对 \(A\) 做 \(d-1\) 次差分,然后可以得出 \(A^{k-1}(0),A^{k-1}(1)\),根据这个解出一次函数表达式 \(y=kx+b\)。然后对 \(B\) 做 \(d-1\) 次差分,可以得出 \(A^{k-1}(s)\),代入进去求解即可。
最后的问题是我们怎么求 \(k\) 阶差分,手玩一下可以得到:
预处理阶乘和阶乘逆元即可,复杂度 \(O(n)\)。
M CF1842F Tenzing and Tree
- 拆绝对值基本功。
考虑设 \(siz_i\) 表示 \(i\) 点内黑点个数,则显然答案就是 \(\sum|2siz_i-k|\)。考虑拆绝对值,分类讨论。容易发现的是只会有一条根链上的点满足 \(2siz_i\ge k\),考虑枚举这个根链的最后一个点。
然后我们考虑加入一个点的贡献,我们计算出将一个点改为黑点后会给它的祖先带来多少贡献,然后从大到小排序累加即可。复杂度 \(O(n^2)\)。
N CF1369E DeadLee
- 这种不好决策的题目还是要想倒着做,然后找一些条件突破。
我们设 \(s_i\) 表示有多少个人喜欢 \(i\)。考虑最后一个人喜欢的菜 \(a,b\),容易发现其中至少有一道菜满足 \(s\le w\),不然它肯定吃不到饭。考虑找出这个 \(s\le w\) 的位置 \(p\),将这个位置上的所有人删掉。由于他们一定能满足要求,所以我们肯定要尽可能让他们往后放。
往后放之后他们一定可以通过 \(p\) 满足要求,所以他们的另一道菜就不需要再保留了,将这些菜的 \(s\) 减去,然后剩下的部分就是一个子问题,递归处理即可。实现时类似拓扑排序,用队列维护即可。复杂度 \(O(n)\)。

浙公网安备 33010602011771号