近期部分思维题总结(rating<=2400)

有 CF/AT 的题,当然也有你谷的部分好题。

持续更新,但是会在今年 Noip 前结束更新,题目按照做题顺序排序。

开头为 CF 的是 CF 题目,AT 的会给出 ABC/ARC/AGC 场次编号及其题目,P 打头的都是洛谷的,别的 OJ 会写明。

篇幅问题,代码只给出链接,部分在 github 上另一部分是对应网站的提交记录(cf 有部分代码是镜像站),看不了可以对应网站上搜 Plozia。

CF1483B Playlist

暴力显然就是枚举点对看能不能删,但是注意到有很多点对重复的,先将所有 \((i,i+1),i \in [1,n)\)\((n,1)\) 丢到队列里面,每次取出队首 \((x,y)\),如果满足删除条件就删掉 \(y\),同时往队尾插入 \((x,z)\),其中 \(z\) 是当前未删除的所有歌中 \(y\) 右边那一首,这个使用链表即可。

时间复杂度 \(O((n+ans) \log V)\)\(V\) 是值域,\(ans \le n\) 是答案,其实就是 \(O(n \log V)\)Code

CF1401F Reverse and Swap

首先翻译四个操作:

  1. Replace(n,k)\(a_n \gets k\)
  2. Reverse(k):将整个序列按照长度 \(2^k\) 分块,然后将每一块全部翻转。
  3. Swap(k):将整个序列按照长度 \(2^k\) 分块,然后第一块与第二块交换,第三块与第四块交换,以此类推。
  4. Sum(l,r):求 \(\sum_{i=l}^{r}a_i\)

这很 ds,考虑线段树。

注意到 \(n\) 也是 2 的次幂,因此这棵线段树一定是满二叉树,层数为 \(\log_2n+1\)

我们规定线段树中叶子节点深度为 0,根节点深度为 \(\log_2n\)(实际实现随意,自己顺手即可),对每一层记录一个值 revrev = 1 则这层所有点的左右儿子互换,rev = 0 则不互换,注意这道题并不用平衡树维护翻转懒标记。

对于 3 操作,直接将 rev[k] 反转,rev[k] ^= 1

对于 2 操作,枚举 \(i\) 从 0 到 \(k\),反转 rev[i]

然后算左右儿子的时候注意 rev 判左右儿子是否互换。Code

CF1416B Make Them Equal

我本来想了个操作数相对较小的做法,结果要求任意时刻 \(a_i\) 非负然后我假了。

先判无解,就是 \(\sum_{i=1}^{n}a_i\) 不是 \(n\) 的倍数,否则能证明有解且所有数最后都是平均数。

实际可以将所有数先全部移到 \(a_1\) 上然后重新分配回去,具体而言对于 \(a_i,i>1\) 考虑将 \(a_i\) 变成 0,全部移到 \(a_1\),由于有部分 \(a_i\) 不满足 \(a_i\)\(i\) 的倍数也就无法将其完全移到 \(a_1\),因此先从 \(a_1\) 分配一部分到 \(a_i\) 使其变成 \(i\) 的倍数再全部搬到 \(a_1\),最后扫一遍将每个数变成平均数。

写代码时注意可能构造的操作顺序会出现部分 \(a_i<0\) 的情况,这个时候调换操作顺序即可(不影响最后结果)。Code

P6196 [EER1]代价

显然,一般情况下一定是先删两端的数更优,于是猜个结论:就是从 1 到 \(n\) 一个个删过去,但是是假的。

然后写出答案式:\(\sum_{i=1}^{n-1}(a_i \times a_{i+1}) + a_n\)

注意到 \(a_i \times a_{i+1}\) 是一定在这个式子里面的(反证即可),因此前一项没法缩小,但是后一项 \(a_n\) 可以改成序列最小值设为 \(a_p\),那么我们先删 1 到 \(p-1\) 然后 \(n\)\(p\)

但是这样是错的,比如 \(a_i,a_{i+1},a_{i+2}\) 三个相邻的数,一般情况有 \(a_i\times a_{i+1}+a_{i+1}\times a_{i+2}\le a_i\times a_{i+1}\times a_{i+2}\),即 \(a_i+a_{i+2}\le a_i\times a_{i+2}\),但是该式在 \(a_i=1\)\(a_{i+2}=1\) 时不成立。

因此我们需要按照若干个 \(a_i=1\) 分段,段内使用 \(\sum_{i=1}^{n-1}(a_i \times a_{i+1}) + \min_{i=1}^{n}a_i\) 计算最小代价,然后将这些 \(a_i=1\) 最后删掉。Code

[USACO 2022 Open Gold] Apple Catching

列出一头牛 \(j\) 能够接到一个苹果 \(i\) 的式子:\(t_j-t_i\ge |x_j-x_i|\)

然后将所有牛和苹果以坐标 \((t_i,x_i)\) 形式画到坐标系内,注意到牛能够抓到的苹果在坐标系内画出来就是个往 \(t\) 轴正方向,倾斜角分别为 45 度和 135 度的两条线中间那块部分。

因此我们将坐标系顺时针转 45 度,就变成了往右上角统计,每个点的新坐标为 \((t_i+x_i,t_i-x_i)\)。注意这里本应除以 \(\sqrt{2}\),但是这道题我们只关心坐标相对大小因此略去了 \(\sqrt{2}\)

image

假设我们转换坐标系后变成了这样,有三头牛 A,B,C,一种正确的贪心方式如下:

先排序,横坐标为第一关键字降序,纵坐标为第二关键字降序,那么图中的点排序为 B,A,C。

然后依次选择苹果,对于每一个点而言,选择纵坐标最低的若干苹果,比如 B 点就会选 3 空间内的。

正确性就是因为 B 先选了 3 空间所以不会和 A 冲突,而 B 又在 C 前选所以保证 B 能选的尽量多,能匹配的就尽量多。

以上只是一种贪心方式,实际上还有几种方式也都是对的,比如排序调换关键字顺序后让 A 尽量选 1 空间之类的。

实现时用一个 multiset 维护即可,但是注意 multiset 删除值的时候会将所有与该值相等的键全删了,删迭代器就不会了。Code

CF438D The Child and Sequence

乍一看区间取模很不可做,于是我们想先暴力做这玩意。

然后如果你会发现每次取模至少砍半或者不变:

  • 如果 \(a<b\),那么 \(a\bmod b=a\) 不变。
  • 如果 \(a>b\)
    • 如果 \(b \geq \dfrac{a}{2}\),则 \(a\bmod b=a-b\geq\dfrac{a}{2}\)\(a\) 为偶数时为 0)
    • 如果 \(b<\dfrac{a}{2}\),则 \(a\bmod b<b<\dfrac{a}{2}\)

综上,我们只需要线段树维护区间和与区间最大值,然后如果区间最大值小于模数就直接退出不执行,否则暴力更新,复杂度是 \(O(n \log n \log V)\)

啥你说单点修改会影响到值进而影响到复杂度?由于是单点修改,所以其至多影响 \(\log n\) 个节点,将这个点重新取模要 \(O(\log V)\),所以单点修改后重新取模回去的复杂度是 \(O(\log n \log V)\),但是你最多只能有 \(m\) 个单点修改所以复杂度是对的。Code

CF1060E Sergey and Subway

考虑题中说的 \(u \to v \to w\) 那么连边 \((u,w)\),即告诉我们每两条边我们可以用一条边代替,因此对于路径 \(x \to y\),如果其连边前路径长度为偶数,最后计算到答案时就是长度除二,如果为奇数则需要整除 2 后加 1。

设连边前总路径长度为 \(ans\),奇数路径的条数为 \(sum\),那么最后答案就是 \(\dfrac{ans-sum}{2}+sum\)\(ans,sum\) 计算就是钦定 1 为根预处理子树大小和深度,每一条边对 \(ans\) 的贡献就是该边两边点数乘积,而只有奇数层的点与偶数层的点之间路径长度为奇数,统计奇数层点个数和偶数层点个数乘起来得到 \(sum\)Code

CF1711B Party

首先 \(m\) 为偶数的情况直接输出 0,因为全选中一定是合法的。

\(m\) 为奇数时先全选,然后有两种方式:

  1. 删去一个度数为奇数的点。
  2. 删去若干个度数为偶数,互相间满足某个特殊性质的点。

其中第一种方式很简单每个点枚举一下即可,至于第二种方案,注意到如果这些偶数点互相之间无连边是不合法的,只有当两个点之间有一条边才行,为保证删去点权值和最小,只选两个连边且度数为偶数的点删去即可。Code

CF1710A Color the Picture

注意到染色方案一定是几行染成一个色,或者几列染成一个色,样例解释的图片比较清晰,下以将几行染成一个色为例。

注意到一行如果与上下两行颜色都不同是不行的,因此要保证每一行都与相邻行中至少一行颜色相同,也就是每个颜色染成一个若干行组成区块。

至于为啥每个颜色不能染成多个若干行组成区块,显然将这些区块移到一起染色更优,自证不难。

据此我们考虑先筛出那些能够染两行以上的颜色,确定每个颜色能染的行数,称每个颜色能染行数减 2 为自由行,那两行为基准行。

注意到每种颜色用了就至少染 2 行,剩下的自由行随便染不染,因此肯定是自由行越多越好,故从大到小排序选颜色,这样保证自由行尽量多,而存在合法方案即有一种选择方式,满足被选颜色自由行之和大于等于总行数减去被选颜色基准行之和。至于按列染色,类似做法。Code

啥你说为啥不直接统计所有颜色基准行 + 自由行的和?样例中第二组数据能解释这一点。

CF1715D 2+ doors

注意到本题可以拆位处理,然后或操作中结果为 0 比结果为 1 更严,因此先确定哪些位必须为 0,开个 book 数组记录下。

考虑预处理 \(v[i][j]\)(vector) 存下第 \(j\) 位中 \(a_i\) 与哪些位置在其后面的数或结果为 1,然后注意到如果这些数中有一个数填 0 那么只能 \(a_i\)\(j\) 位填 1 剩下别填,否则就将后面这些数第 \(j\) 位设为 1。

有个细节,如果 \(a_x|a_x=z\),那么 \(a_x=z\),此时所有位置都不能动,但是里面会有一些位置是 1,注意这些不能动的 1 的位置同样不能动。Code

CF1715E Long Way Home

首先跑 dijkstra 知道不通过航空的结果,然后考虑从航空次数最多为 \(k\) 推到 \(k+1\),如果以航空结尾有式子 \(f_{k+1}(u)=\min f_{k}(v)+(u-v)^2\),然后注意到拆出来是一个一次函数形式所以李超线段树维护谁写单调队列维护凸包啊,注意需要先将所有 \(f_{k}(v)\) 拆出来的斜率与截距都丢到李超线段树里面然后再转移,也因此 \(f\) 一维就够了,但显然有部分点是走边然后航空再然后走边,所以将得到的新 \(f\) 全部丢到堆中再跑 dijkstra 即可。Code

CF874E Packmen

首先注意到如果时间 \(t\) 可行则 \(t+1\) 可行,因此二分答案,于是问题变成验证方案,然后将所有包装和人分别按位置升序排序,枚举人吃包装,注意到一个人只会转一次并且会吃掉沿途所有食物,因此每次先往左吃掉上一个人没吃掉的然后往右吃,当然走法可以先右再左也可以先左再右,可行性判断就是某个人已经无法吃掉他最左边还没吃掉的食物即无解,最后没吃完无解。Code

CF893E Counting Arrays

首先可以有负数的条件就是全正数答案乘上 \(2^{y-1}\) 因为前面的数可以随意正负,最后一个数根据前面正负情况决定即可,然后考虑将 \(x\) 分解质因数,对于每个质因数 \(p_i^{k_i}\),相当于 \(k_i\) 个相同的球放到 \(y\) 个不同的盒子方案数,为 \(C_{k_i+y-1}^{y-1}\),所以最后答案就是 \((\prod_iC_{k_i+y-1}^{y-1})\times2^{y-1}\),注意这道题好像有点卡常就是分解质因数和算答案要放在一起写,分解质因数的写法常数要小点。Code

CF1677B Tokitsukaze and Meeting

注意到行和列可以分开统计,对于列可以考虑以 \(i\%m\) 为标准分组因为若 \(i\%m=j\%m\) 那么 \(i,j\) 在一列,这样可以统计每一列的答案,对于行考虑从 \(i-m\) 转移,相当于 \(i-m\) 上面填 1 行,只要这行里面有一个位置是 1 就行,这个记录下上个 1 的位置即可。Code

CF1677C Tokitsukaze and Two Colorful Tapes

考虑贪心,将所有环处理出来然后按照 1,n,2,n-1... 的方式填数,特别的奇数长度环最后一个数先不填,等填完后再随意放因为这个数是无效的,这样会最大。

另外考虑将每个环的环形数列 \(\{a_m\}\) 拿出来,如果一个数比相邻两个大就叫其山峰,如果比相邻两个小就叫其山谷,否则就是山坡。显然山峰对答案贡献为 \(2a_i\),山谷贡献 \(-2a_i\),山坡贡献 0,而对于一个长为 \(len\) 的环,有 \(\lfloor\dfrac{len}2\rfloor\) 个山峰和山谷,计算出所有的山峰山谷后(设有 ans 个),将山峰分别赋值为 \([n-ans+1,n]\),山谷分别赋值为 \([1,ans]\),等差数列求和得答案为 2 * ans * (n - ans)Code

CF1682D Circular Spanning Tree

先判无解,如果 1 的个数是奇数或者没有 1 则无解。

讨论 \(n\) 为偶数且全为 1 的情况,此时 \(1\to i,i\in[2,n]\) 即可。

剩下情况序列中必然有一个 0,将这个 0 作为树根,然后将字符串循环后剩下 \(n-1\) 位分割成 \([0,0,...1]...\),就是一堆 0(可能没有)加上一个 1,注意最后一位必须是 1 所以根不要乱选,然后这些区间内顺次连边,第一个数与树根连边即可。Code

CF895C Square Subsets

这题有状压 dp 解法,但是有一种简洁的线性基做法。

注意到平方数只与其质因数指数的奇偶性相关,而 70 以内质数只有 19 个,考虑将原数组质因数分解,然后状压 19 个质数,质数指数为奇数的位置标为 1,将这些数压入线性基,设线性基大小为 \(c\),那么可以证明剩下的 \(n-c\) 个数随便选,线性基中都能选出同样的数异或,而不选线性基外的数则无法使异或和为 0,因此答案就是 \(2^{n-c}-1\)Code

题目保证 \(a_x,a_y\ge2\),因此可以证明从起始点开始先尽量往第一个数据点走然后往大了走更优,又 \(2^{64}>10^{18}\),所以大概存个 64 个点就差不多了,存的点中最后几个坐标大的点保证能走到即可,每次枚举一个点 \(i\) 表示起始点先走到这个点,然后往第一个点(坐标最小点)走,再走回去,所有结果取最大值即可。Code

CF1700D River Locks

首先求出所有 \(v_i\) 的和记为 \(sum\),那么显然答案就是 \(\lceil\dfrac{sum}{t}\rceil\),但有个问题是前面若干个水源可能 \(t\) 时间内装不满,比如 \(v_1=4\) 时如果 \(t<4\) 那么答案就是 -1,因为第一个水槽装不满,因此还需要考虑一个时间下界 \(\max\lceil\dfrac{\sum_{i=1}^{k}v_k}{k}\rceil\),时间小于这个下界就不行否则都行。可行方式就是直接从第一个开始开。Code

CF1413C Perform Easily

将所有 \(b_i-a_j\) 丢到数组里面,从小到大排序,双指针维护一下,每次指针移动到合法区间就更新答案,合法区间指对于所有 \(i\in[1,n]\) 都有一个 \(b_i-a_j\) 在区间内。Code

CF1415E New Game Plus!

注意到答案其实就是将若干个数分成 \(k+1\) 组,每组内部显然是非严格降序排列最优,因此维护一个大根堆,将 \(c_i\) 非严格降序排序,每次取出堆中最大值加入答案内然后将当前没放进去的最大值加到这个最大值里面丢进去。Code

CF1415D XOR-gun

考虑答案上界,如果有连续三个数二进制最高位相同那么一次操作即可,否则必然有 \(n\le60\),注意到此时最优方案一定是对两个相邻的区间 \([i,j],[j+1,k]\) 分别异或后满足题意,前缀异或和然后 \(n^3\) 暴力即可。Code

posted @ 2022-05-19 20:44  Plozia  阅读(159)  评论(0)    收藏  举报