Atcoder 乱做

Posted shichengxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Atcoder 乱做相关的知识,希望对你有一定的参考价值。

最近感觉自己思维僵化,啥都不会做了……

ARC103 F Distance Sums

题意

给定第 (i) 个点到所有点的距离和 (D_i) ,要求构造一棵合法的树。满足第 (i) 个点到其他所有点的距离和为 (D_i)

(n le 10^5)

技巧

寻找特殊的量,推出整个树的形态

题解

整棵树里头,最为特殊的点有两类。一个是重心,这是距离和最小的点,另一个是叶子节点,这是距离和最大的节点。考虑如果我们先确定重心,那么接着就不大好往下推了,因为我们并不知道子树的大小。考虑从叶子节点往上推,记录当前子树的大小,这样我就可以直接得到父亲节点的距离和。由于题目保证了所有点的距离和各不相同,因此我可以直接确定这个点的父亲。注意往上一直推到根节点之后,还需要检查一遍根节点的距离和是不是正确的。因为我们这么做只保证了相邻节点的距离和的差值的正确性。

ARC101 E Ribbons on Tree

题意

给定一棵 (n(n equiv 0 mod 2)) 个节点的树,你需要将这 (n) 个节点分成 (frac{n}{2}) 组,每组两个节点。这 (frac{n}{2}) 组点对会形成 (frac{n}{2}) 条路径。求有多少种不同的分组方案,使得树上每条边都至少被其中一条路径覆盖。

(n le 5000)

技巧

利用容斥原理简化限制。

题解

直接 DP 只能做到 (O(n^3)) 的复杂度。直接 DP 大概就是设 (dp_{i,j}) 表示 (i) 号点的子树,孩子到父亲的边被 (j) 条边覆盖的方案数。由于合并的时候必须要枚举多少条链相接,因此复杂度会来到 (O(n^3))

考虑容斥,那么这棵树可以视作断成若干个联通块,联通块内随意配对。这样如果直接做 (n) 遍 DP ,仍然是 (O(n^3)) 的,因为你需要做 (n) 次 DP,每次 DP 仍然需要记一个当前子树大小。

考虑做 (n) 遍 DP 有一些浪费,能不能把容斥融到 DP 里头呢?答案是可以的。你只需要在选择断掉一条边的时候,乘上一个 (-1) 的转移系数就可以了。

ARC 101 F Robots and Exits

题意

数轴上有 (n) 个机器人和 (m) 个出口。每次你可以对 (n) 个机器人的坐标同时 (+1)(-1) 。当一个机器人的位置上恰好有一个出口的时候,机器人就会从出口消失。求有多少种不同机器人走出出口的方案数。两种方案不同,当且仅当一个机器人从不同的出口消失。

(n le 10^5)

技巧

巧妙建模转化题目

题解

首先每个机器人只会从他左右两个出口消失。考虑将每个机器人抽象成二维平面上的一个点,这个点的横坐标表示这个机器人距离左边出口的距离,纵坐标表示这个机器人距离右边出口的距离。那么一个方案就可以抽象成从 ((0,0)) 出发至 ((infty,infty)) 一条轮廓线。这条轮廓线左上角的机器人即从左边出口消失,否则从右边出口消失。于是我们只需要统计轮廓线的方案数。

考虑轮廓线如何统计不会记重。设 (dp_i) 表示经过第 (i) 个点的轮廓线方案数。那么接下来合法的转移点为第 (i) 个点右上角的所有点,表示轮廓线先向上走一段,再向右走剩下的一段。DP 可以用树状数组优化。时间复杂度 (O(n log n))

ARC100 F Colorful Sequences

题意

给定一个长度为 (m) ,字符集大小为 (k) 的母串。求所有满足以下条件的字符串中母串出现次数之和。

  1. 该字符串的长度为 (n),字符集大小为 (k)
  2. 这个字符串至少包含一个子串满足这个子串是一个 (1)(k) 的排列。

(m le n le 25000,k le 400)

技巧

考虑母串对答案的贡献。

题解

母串在某个串的出现次数,如果使用字符串的思路,会非常不好做。考虑母串对答案的贡献,如果我们确定了母串在最终字符串的出现位置。那么抛开第二条限制,母串两边的位置就可以随意填了。

考虑加上第二条限制之后该怎么做。如果母串中包含了两个相同的字符,那么这个 (1)(k) 的排列一定不会跨过母串。所以这个排列一定会出现在母串的两侧。只要计算出母串从左右两侧出发的极长不重复序列的长度,就可以向左向右分别 DP 了。DP 大概就是记 (dp_{i,j}) 表示当前考虑到第 (i) 个字符,从第 (i - j + 1) 个位置到第 (i) 个位置各不相同,且第 (i) 个位置和第 (i-j) 个位置相同的方案数。DP 利用前缀和可以做到 (O(nk)) 的复杂度。

如果母串中包含的字符各不相同,那么每个字符都是等价的。考虑将所求转化为,求出满足条件的字符串中,包含了长度为 (m) 且这 (m) 个字符互不相同的子串出现次数之和,最后只需要将答案除一个 (inom{k}{m}m!) 。计算的过程可以用类似第一种情况的一个 DP 解决。需要多记一维表示是否合法,多记两个数组表示出现次数之和。

注意如果这个母串如果包含了一个 (1)(k) 的排列,需要特判一下。

代码长度 ( exttt{3.4Kb}) 的 DP 题……

ARC099 F Eating Symbols Hard

题意

给定一个长度为 (n) 的字符串,这个字符串由 +->< 四种字符。求这个字符串有多少子串的权值与原串相同。

一个字符串的权值定义为,按照顺序执行这个字符串的操作。+ 操作会对指针所在位置 (+1)- 操作会对指针所在位置 (-1)>,< 操作分别会将指针右移或左移。指针最开始位于 (0) 处,两个字符串的权值相同当且仅当按照操作生成的数组每一位都相同。

(n le 250000)

难得的会做的 F 题……

题解

注意到两个字符串拼接之后的数组可以直接 (O(1)) 合并,因此可以利用 Hash 解决。所以思路就比较简单了。只需要将每个前缀插到哈希表里头,然后对每个前缀去掉一个等长的前缀,再和母串匹配。去掉前缀可以转化为给母串加上一个前缀。因此只要对母串加上一个前缀,再到哈希表里头查就可以了。

ARC098 F Donation

题意

给定一张 (n) 个点,(m) 条边的图。这张图的每个点有两个权值 (a_i,b_i)。你将会从这张图中选出一个点作为起点,随后开始遍历这张图。你能到达一个节点 (i) 当且仅当你的手上有至少 (a_i) 元钱。当你到达一个节点 (i) 后,你可以选择对这个点捐赠 (b_i) 元。你需要对每个点捐赠一次。问你身上至少要带多少元钱?

(n,m le 10^5)

技巧

太神了……都不知道技巧在哪里……

题解

首先可以注意到两个性质

  1. 你一定会在最后一次经过某个点的时候对这个点进行捐赠。
  2. 定义 (max(a_i - b_i,0)) 为这个点的权值,那么权值越大的点会尽量放到前面捐赠。

第一个性质比较显然,因为捐赠之后你手里的钱会变少。因此如果我们把捐赠放到最后一次经过那个点,方案不会更劣;考虑我们如果保证了第一条性质,我们会得到这样一个捐赠的方式:首先确定一个点,依次捐赠这个点的子联通块,留下一个子联通块,随后捐赠这个点,最后捐赠剩下的这个子联通块。

第二条性质的前提是第一条性质。即在满足第一条限制的前提下,再去尽量满足第二条性质。假设我们确定的这个点权值不是最大的,那么考虑交换这个点与权值最大的点,一定不会更劣。形象化地理解就是,如果我们把权值大的点放到前面,会给后面的点留下一定的空间,多花的权值会更少一些。如果想要形式化的理解,可以等会看 DP 的式子就能理解了。

得到了这两个性质,我们稍微理一下思路。每次从全局选择一个权值最大的点,断掉这个点会形成若干个联通块。接下来需要找出最后遍历哪个联通块是最优秀的。寻找这个最优秀的联通块可以利用 DP 来解决。一直这么递归下去就可以得到一棵树。到这里 DP 应该比较简单了,设 (dp_i) 表示 (i) 号点的子树需要多花的最少的钱数。那么就会有

[dp_x = min{A_x,max(dp_y,A_x - Sum_y)}]

其中 (A_x) 表示 (x) 的权值,(Sum_x) 表示 (x) 子树的 (b) 值之和。最后 (dp_{rt} + Sum_{rt}) 即为最后的答案。DP 不需要将树建出来,直接用个并查集维护一下即可。

ARC097 F Monochrome Cat

题意

给定一棵 (n) 个点的树,树上每个节点会有黑白两种颜色。有一只猫在树上走,它可以自由地选择起点。它可以对这棵树执行以下两种操作。

  1. 翻转它所在的节点的颜色,这需要花费 (1s)
  2. 走到一个和它当前位置相邻的节点,并翻转新节点的颜色,这需要花费 (1s)

问最少需要花费多少时间可以把这个树变为全黑的。

(n le 10^5)

技巧

将路径连成环,考虑多余贡献

题解

这题基本算是自己搞定的吧……

首先发现起点和终点自由确定是件很烦的事情。因此考虑将这条路径先连成一个环。这样我们可以直接得到环的最小答案。环的最小答案,即不多走任意一个黑点所形成的路径。于是我们可以定一个白点为根,将整棵子树均为黑色的子树删掉。这样答案即为树上的边数的两倍,加上需要调整的点数。一个点需要调整,当且仅当它经过度数次翻转之后,颜色为白色。

再考虑从这个环中删掉一条路径,显然需要删掉一条贡献最大的路径。发现将一个需要调整的点删去会减少 (2) 的贡献,否则贡献不会改变,于是只要在树上找直径即可。注意需要加上一些特判。

ARC096 E Everything on It

题意

一个拉面餐厅有 (n) 种配料,一碗拉面可以任意添加任意的配料,也就是说,一碗拉面可以添加 (2^n) 种不同的配料组合。一个人要来拉面餐厅买若干碗拉面。求他有多少中不同的方式,满足以下两个条件:

  1. 所有购买的拉面的配料各不相同
  2. 每种配料在所有购买的拉面中至少出现两次

(n le 3000)

技巧

容斥原理简化限制,暴力容斥优化

题解

这种限制容易让人想到容斥原理。如果直接暴力容斥,枚举至少 (i) 种配料没有出现,至少 (j) 种配料只出现一次,还需要枚举一维 (k) 表示只出现一次的配料划分为了多少个集合。这样似乎是 (O(n^4)) 的?反正我只会做到这个复杂度……可以得到部分分。

考虑枚举两维有些浪费,如果两维放到一起枚举,只容斥一维,会怎样呢?

枚举至少有 (i) 种配料出现不超过一次,再枚举这出现了一次的数划分为了 (j) 个集合,最后枚举出现了一次的个数 (k) 就会有一个这样的式子。
[ ans_i = (2^{n-i})^j2^{2^{n-i}}inom{n}{i}sum_{k=j}^iS(k,j) inom{i}{k} ]
注意到 (displaystylesum_{k=j}^iS(k,j) inom{i}{k} = S(i + 1,j + 1)) ,因此这个式子可以 (O(n)) 求。

关于斯特林数这个式子,可以理解为,先多加一个标记数,将这 (i + 1) 个数划分为 (j + 1) 个集合,最后将这个标记数所在的集合删掉。

ARC096F Sweet Alchemy

题意

给定一棵 (n) 个点的树和两个参数 (D,X),每个点会有一个权值 (w_i) 和费用 (v_i) 。每个点的权值需要满足 (w_{fa_i} le w_i le w_{fa_i} + D) 。要求 (displaystyle sum_{i = 1}^{n} w_iv_i le X) 并最大化 (displaystylesum_{i=1}^{n}w_i)

(n le 50,X,D,v_i le 10^9)

技巧

对于种类比较少,权值比较大的多重背包特殊解法。

题解

对树做一下差分,容易把原题转化为一个背包的模型。相当于你可以对一个点的子树加上一个小于等于 (D) 的权值(w),并产生 (wsum v_i) 的代价,要求最大化权值和。对于这种特殊的背包模型该如何处理呢?

在最开始学背包的时候,会有一个错误的想法:对于权值为 (v_i),代价为 (w_i) 的若干物品,我们计算出它们的性价比,贪心的选择其中性价比高的部分物品。这样之所以是错的,是由于物品不能分割,这样会有空闲的地方出现但又不能塞入更好的物品了。于是我们考虑:在什么样的情况下可以直接用性价比高的物品代替性价比低的物品呢?

考虑两个物品 (v_i,w_i)(v_j,w_j),其中 (frac{v_i}{w_i} > frac{v_j}{w_j})(i) 物品的性价比高于 (j)。如果我们选择了 (v_i) 个物品 (j),不如直接更换成 (v_j) 个物品 (i)。这样权值是相等的,都是 (v_i imes v_j),但代价却更小:(v_j imes w_i < v_i imes w_j)。由此我们知道:在可以选择性价比更高的物品却没有选择的情况下,性价比低的物品最多选择 (v_i?1) 个。而这个 (v) 的范围是很小的,所以我们可以对于每一种物品都从其中拿出 (min(n,D)) 件来进行多重背包,剩下的贪心即可。

以上题解来自 Twilight_Sx‘s blog

代码并没有写,感觉没啥意思。

以上是关于Atcoder 乱做的主要内容,如果未能解决你的问题,请参考以下文章

线段树乱做GSS

杂题乱做4

codeforces 乱做题记录

Web公路,新手上路!NO.3 [ 乱做一通的基本视频网页]

AtCoder Nuske vs Phantom Thnook AtCoder

AtCoder Beginner Contest 234