AtCoder ABC 杂题记录
ABC 做题记录
ABC001-099
Nothing Yet.
ABC100-199
*ABC141F(Difficulty: 2342)
题意:给出一个长为 \(n\) 的数组 \(a_i\),要求分成两个非空集合。一个集合的价值为其元素异或和,一种划分方案的价值为两集合价值之和。求最大价值。
\(1\le n\le 10^{5},0\le a_i\lt 2^{60}\)
解法
不难注意到,若某位有奇数个 \(1\),则其对答案的贡献恒为 \(1\)。
将这部分的答案先算上,将这些位都改成 \(0\)。剩下位要么均为 \(0\),要么均为 \(1\),故分出的两集合的异或和是相同的。用线性基跑出最大异或和后乘二即可。
ABC200-299
ABC200E
题意:定义一个三元组 \((i,j,k)\) 的排序方式为:以 \(i+j+k\) 为第一关键字,\(i\) 为第二关键字,\(j\) 为第三关键字。求所有 \(1\le i,j,k\le N\) 的三元组中,排名为 \(K\) 的。
\(1\le N\le 10^{6},1\le K\le N^{3}\)
ABC214F
水题。
题意:对于一个串 \(S\),求其本质不同的子序列 \(T\) 的数量,满足其组成位置在 \(S\) 中不相邻。
解法:
\(1\le n\le 2\times 10^{5}\)。
容易想到 DP,设 \(f_{i}\) 表示子序列最后一个位置选择了 \(i\) 的方案数,考虑会算重,将 \(f_{i}\) 减去所有 \(j<i\) 的 \(f_j\) 即可,前缀和优化。
ABC217F
细节还是考虑得不够,如果没有大样例就寄了。
题意:\(2N\) 个人排成一排,给定 \(M\) 对好朋友,每一次操作可以删除一对相邻的好朋友,求将整个序列删空的方案数。
\(1\le N\le 200,0\le M\le N(2N-1)\)
解法:
一开始毫无头绪,后来一想这不就区间 DP?直接设 f[i][j] 表示区间 [i,j] 删空的方案数,转移考虑将 i 和 j 配对删空,或是将区间拆成两半,方案数相乘,再乘一个组合数。
然而喜提 WA,为什么?当合并三个区间时显然会算重(合并 1,2 再合并 3,与合并 2,3 再合并 1)
所以需要钦定一下使得它无法算重。具体来说,钦定右区间不是由若干个区间合并得来的。枚举断点 \(k\) 并钦定其与 \(r\) 匹配,这样就能避免算重。
ABC239F
题意:给定一个 \(n\) 个节点,\(m\) 条边,要求补充 \(n-m-1\) 条边,使得图变为一棵树。给定每个点的度数,给出构造方案或报告无解。
解法:
想到可以用并查集维护联通信息,每一次找两个未满足条件的一个连通块中不满足条件的点连起来。
但是这样会有问题,具体来说,样例过不了。
事实上,问题出在只有一个点度数和需求相差一的连通块上。假设现在有三个连通块,有两个与要求相差 1,有一个相差 2,可能前两个连通块相连了,整个图就不连通了。
所以每一次相差 1 的块要尽可能和相差大于 1 的块连接。如果没有相差 1 的块,则无解。如果没有相差大于 1 的块,就要求相差 1 的块恰好有两个,否则无解。
无解情况真多。
ABC249E
感觉挺水的,不知道怎么就评到一千九了。题意是说对于一个字符串,定义压缩形式为字母加重复次数。例如 aaaaabbbc 被压缩为 a5b3c1。
求有多少个长度为 \(n\) 的字符串满足其压缩之后长度不超过 \(n\)。要求 \(O(n^2)\)。
解法:
一看就是直接 DP,暴力 DP 设 \(f_{i,j}\) 表示原串和压缩串长度,前缀和优化一下就好了。
ABC259Ex
fydj 告诉我的题目。
给定 \(N\times N\) 的矩阵,每个格子有一种颜色,每一步只能向下走或向右走。求起点终点为同一种颜色的路径数量。
\(1\le N\le 400\)
解法:
这种分颜色考虑的,经典做法是值域分治。
首先容易想到,枚举两个颜色相同的位置分别作为起点和终点,用组合数计算。假设有 \(B\) 个该颜色的格子,可以做到 \(O(B^2)\)。
另外,还可以 DP 计算,设 \(f_{i,j}\) 表示走到位置 \((i,j)\) 的方案数,很容易转移,可以做到 \(O(N^2)\)。
平衡一下,当某种颜色出现次数不超过 \(N\) 次时,用第一种做法,否则用第二种做法,时间复杂度是 \(O(N^3)\),可以通过。
ABC265F
题意:在 \(n\) 维平面上,定义两个点的曼哈顿距离为 \(\sum_{i=1}^n|x_i-y_i|\),给定两个点,求到这两个点距离均不超过 \(d\) 的点数。
\(1\le n\le 100, 1\le d\le 1000\)。
解法:
一想就发现每一维好像是独立的,可以设 DP \(f_{i,s_1,s_2}\) 表示前 \(i\) 维空间,与给定点距离分别为 \(s_1\) 和 \(s_2\) 的点数。那么很容易得到 \(O(n\times d^4)\) 的做法。这样状态数是 \(O(nd^2)\) 的,非常好,考虑用前缀和之类的东西优化一下使得转移变为 \(O(1)\)。
发现每一维相当于是一个数轴,距离两个点 \(p_i\) 和 \(q_i\) 的距离有两种情况:在其之间或在外侧。
-
对于在 \(p_i\) 和 \(q_i\) 之间的情况,假设到 \(p_i\) 距离为 \(x\),到 \(q_i\) 距离为 \(y\),那么 \(p_i\) 到 \(q_i\) 的距离 \(x+y\) 是一个定值 \(\lvert p_i-q_i\rvert\)。记其为 \(\Delta\),那么有转移 \(f_{i,s_1,s_2}=\sum_{x,y}f_{i-1,s_1-x,s_2-y}\),发现如果记录所有和为 \(s_1+s_2-\Delta\) 的 \(f\) 之和,就能 \(O(1)\) 转移了。注意这里要限制 \(x\le s_1\) 和 \(y\le s_2\),所以记 \(g_{i,j}\) 表示和为 \(i\) 前 \(x\) 不超过 \(j\) 的点数即可。
-
另一种情况,有转移方程 \(f_{i,s_1,s_2}=\sum_{x}f_{i-1,s_1-x,s_2-x-\Delta}\),在另一侧类似。容易发现维护 \(g_{i,j}\) 表示 \(\sum_{x\le i,y\le j}f_{i-1,x,y}\) 也可以做到 \(O(1)\) 转移。
做的时候刚开始还想假了,还调了挺久,35 分钟的题做了 80 分钟。还不是因为不够努力。
感觉挺板,或者说挺自然,但是不知道为什么是紫题。
ABC275Ex
题意:给定两个序列 \(a\) 和 \(b\),每一次操作可以选定一段区间,将区间中的 \(a\) 减 1,代价为区间中 \(b\) 最大值,求将 \(a\) 的最大值变为 \(0\) 的最小代价。
\(1\le n\le 10^{5}\)
解法:
转化:每一次必然操作一个极大的区间 \([l,r]\),使得 \(b_{l-1},b_{r+1}>\max_{i=l}^{r}b_i\)。
以 \(i\) 满足二叉搜索树性质,\(b_i\) 满足堆的性质,建立笛卡尔树,每次操作等价于将子树减 \(1\),花费为 \(b_{rt}\)。
设 \(f_{i,j}\) 表示使 \(i\) 子树最大值不超过 \(j\) 的最小花费。设 \(i\) 两个儿子为 \(x\) 和 \(y\),有转移:
有结论若以 \(f_{i,j}\) 为因变量,\(j\) 为自变量,那么得到的函数是下凸的。具体证明可以归纳:每一次加一条直线,取前缀 \(\min\),那么得到的一定是下凸的。
那么可以用 slope trick 优化,利用 map 启发式合并。具体可以参考 这篇题解,感觉讲得很清晰。
一开始启发式合并还写假了。
ABC297F
题意:给定一棵树,边有边权,点有点权。要求选出任意条边,使得每一个点相连边中选中的边数量不超过点权,求最大选中边权和。
解法:
唐了,写了一个假的 DP,直接寄飞了,做了一个半小时破防了。
设 \(f_{i}\) 表示点 \(i\) 与父亲相连的边选,\(g_i\) 表示不选的最大贡献。转移时先考虑从 \(i\) 到儿子的边全部不选,则 \(f_{i}=g_{i}=\sum f_{son}\),再考虑是否要选择到儿子的边。如果选中一条边,那么贡献为 \(g_{son}+w(i,son)-f_{son}\),将其排序后选择即可。
ABC300-399
ABC348F
这题洛谷评分是黄,题意是说给 \(n\) 个序列,每一个长度为 \(m\)。如果两个序列同一个位置的值相同,称这个位置是好的,如果好的位置数量是奇数,那么称这两个序列是好的。求 \(n\) 个序列两两能够组成多少个好的序列。
\(1\le n,m\le 2000,1\le a_{i,j}\le 999\)
解法:
这个数据范围很奇特,正解是 bitset,看了洛谷题解,发现暴力用位运算,不用 if,交 clang 或者开火车头可以过,就没有写 bitset。
ABC356F(Difficulty: 2152)
题意:
给定常数 \(K\),维护一个集合 \(S\),定义两个数 \(a\) 和 \(b\) 连通,当且仅当 \(\mid a-b\mid \le K\)。
有 \(q\) 次操作,第 \(i\) 次操作为:
-
1 x,若 \(S\) 中有 \(x\),则将其删除;否则,将其插入。 -
2 x,保证 \(x\) 在 \(S\) 中,询问 \(x\) 所在连通块的大小。
\(1\le q\le 2\times 10^{5},1\le K,x\le 10^{18}\)
解法
首先连通块在值域上连通。
若维护 \(b_i\) 表示 \(i\) 与其后继是否连通,\(a_i\) 表示 \(i\) 是否在集合中。则 \(x\) 到 \(y\) 连通等价于 \(b_x\) 到 \(b_{y-1}\) 的和等于 \(a_x\) 到 \(b_y\) 的和。于是用线段树维护这两个东西。查询时二分左右,判断即可。
ABC358F
要求在 \(n\times m\) 的方阵上布置一个迷宫,使得迷宫的长度只有唯一一条路径,路径长度恰好为 \(k\),
解法:
讨论一下,模拟一下。
ABC359F
题意:
给定 \(a_i\),任意构造一棵树,假设点 \(i\) 的度数为 \(d_i\),最小化并输出最小值:
\(2\le n\le 2\times 10^{5},1\le a_i\le 10^{9}\)。
解法:
贪心,唉。
一棵树总度数为 \(2(n-1)\),先给每一个点分配 \(1\) 的度数。剩下的 \(n-2\) 度数就可以任意分配(可以认为每分配一个度数就与一个之前预分配 1 度数的点连边)。于是用堆来得到增量最小的点,将其选择。
ABC360F
给定 \(n\) 个区间 \([l,r]\),定义区间 \([l_1,r_1]\) 和 \([l_2,r_2]\) 相交当且仅当 \(l_1<l_2<r_1<r_2\) 或 \(l_2<l_1<r_2<r_1\)。
求 \(0\le L<R\le 10^{9}\),使得 \([L,R]\) 与给定区间相交数量尽可能多。如有多解,输出字典序最小的一组。
解法:
将相交的条件进行转化,例如 \(l_i<L<r_i<R\),可以重新表述为 \(l_i+1\le L\le r_i-1\) 且 \(r_i+1\le R\le 10^{9}\)。
如果将 \(l\) 看作 \(x\) 轴,将 \(r\) 看作 \(y\) 轴,那么这是一个矩形的形式。
原问题变为矩形覆盖,查询平面单点最大值。扫描线即可。
注意 \(L\not=R\)。
ABC360G
题意:给定一个长度为 \(N\) 的序列 \(a\),需要进行 1 次修改,将某个值改为任意值,求最长上升子序列长度。
\(1\le N\le 2\times 10^{5}\)
解法:
解法:发现只要 LIS 中出现两个相邻位置的差值大于 1 并且位置差值也大于 1,或是首或尾不在 LIS 中,答案都可以增加 1。一样用树状数组维护,但是同时记录 LIS 末尾为某一个值的最长情况下的最小位置。这样就可以转移了。
ABC363F
题意:给定数字 \(N(1\le N\le 10^{12})\),求一个字符串 \(S\),满足其长度不超过 \(1000\),且仅包括除 \(0\) 以外的数字和 * 号,这个算式的结果需要等于 \(N\)。
解法:
直接暴力?
设 \(f(n)\) 表示将数字 \(n\) 转化为符合题意的字符串的结果,如果不存在,则 \(f(n)\) 为空串。
若表达式形如 s*rev(s),可以转化为 s*1*rev(s)。若 s 比 rev(s) 大,则交换两者,仍然合法。
枚举 \(n\) 的因数 \(i\),则 \(\text{rev}(i)\) 也需要是 \(\frac{n}{i}\) 的因数,如果满足条件,就递归求解。
这样看起来很暴力,题解中有证明复杂度是 \(O(d(n)^2)\) 的,其中 \(d(n)\) 表示 \(n\) 的因数个数,且由于有很多状态不会被访问到,所以它跑得“相当快”。
ABC365F
SB 题,做得我破防,不做了。
ABC368E
E 比 F 和 G 难?
题意:
有 \(n\) 个城市 \(m\) 列火车,第 \(i\) 列从城市 \(a_i\) 驶向 \(b_i\),在时刻 \(s_i\) 出发,在时刻 \(t_i\) 到达。
现在列车要晚点了,第 \(i\) 列火车晚点 \(x_i\) 时刻。现给定 \(x_1\),请构造非负 \(x_2,x_3,\cdots,x_m\) 使得 \(x\) 之和最小,并且满足以下条件:
-
若有 \(i,j\) 满足 \(a_i=b_j\) 且 \(t_j\le s_i\),要求 \(t_j+x_j\le s_i+x_i\) 仍然成立。
-
换句话说:若可以从列车 \(i\) 换乘到列车 \(j\),那么晚点之后仍然要满足条件。
\(2\le n,m\le 2\times 10^{5}\)
\(0\le s_i<t_i\le 10^{9}\)
\(1\le x_1\le 10^{9}\)
解法:
做了一个小时的差分约束,你告诉我正解是贪心?
看到那个式子非常好,直接差分约束,发现边数爆炸,直接前缀和优化。发现有正有负,数据范围跑不了 SPFA,想起来 [ABC232G] Modulo Shortest Path 的建图技巧,可以参考一下。建完跑出来发现一组约束都无效,应该是要建负边,跑最长路,已经浪费一个小时,懒得改了。
实际上,按照 \(s\) 排序之后,所有原来可能换乘的列车都在前面,并且只要令 \(x_i\) 等于 \(\max(t_j+x_j)-s_i\) 即可,且这样一定是最小的。用树状数组维护一下即可。
这里要求 \(x\) 的和最小,其实不是经典的差分约束,不应该直接开始就想差分约束的。
ABC368F
直接 D 了,绿色的。
有一瞬间我是想对了:是不是直接转化为 NIM 游戏,但是不知道为什么被我否掉了,转而一个奇怪的方向,然后 WA 飞了。
ABC368G
如果我做这场是不是要输麻了?不会 E 不会 F 不会 G?
给定两个长为 \(n\) 的序列 \(a_i\) 和 \(b_i\),有三种操作:
-
给定 \(i,x\),将 \(a_i\) 变为 \(x\)。
-
给定 \(i,x\),将 \(b_i\) 变为 \(x\)。
-
给定 \(l,r\),求一下问题的最大答案:
- 初始令 \(v=0\),\(i\) 从 \(l\) 枚举到 \(r\)。将 \(v\) 替换为 \(v+a_i\) 或 \(v\times b_i\),最后 \(v\) 的值是多少?
\(1\le a_i,b_i\le 10^{9}\)
\(1\le n,q\le 10^{5}\)
保证操作 3 的答案不超过 \(10^{18}\)
解法:
一开始以为保证答案不会爆 long long 是为了不用写高精度,其实只要想一想就知道 \(b\) 不为 \(1\) 的位置不会太多,而选 \(b_i=1\) 还不如不选,所以会选择 \(a_i\)。
所以用 \(set\) 维护一下 \(b\) 不为 \(1\) 的位置,再用线段树或树状数组维护一下 \(a\) 的区间和即可。
ABC369F
30 分钟。
水题,直接求 LIS 就行了,但是排序的时候没有按双关键字排序,直接卡了我二十分钟。
ABC372F
16 分钟。
设 \(f_{i,j}\) 表示时刻 \(i\) 位于位置 \(j\) 的方案数。发现前 \(N\) 条边相当于在 \(i\) 加 1 时 j 也加 1,所以可以改变状态设计,记 \(f_{i,j}\) 表示位置 \((j+i)\bmod N\) 的方案数。此时后 \(M\) 条边会改变答案。而后 \(M\) 条边很少,直接暴力转移即可。
ABC377F
题意:给定一个 \(n\times n\) 的棋盘,上面有 \(m\) 个皇后,每一个皇后的攻击范围是上下左右对角线,问有多少个位置不会被任何皇后攻击。
\(1\le n\le 10^{9},1\le m\le 3000\)
解法:
每一个皇后的攻击可以表示为四种直线,每一条直线覆盖的位置数量很容易计算。但是会有重复计算的。
将这些直线去个重,每一种直线内部互相平行,一定不会重复覆盖一个格子。任意两种不同直线只有一个交点。
枚举两条直线,计算交点。用 map 存下每一个交点被计算次数。若一个点,
-
被计算 1 次,说明有两条直线覆盖了这个点。
-
被计算 3 次,说明有三条直线覆盖,即,\(\binom{3}{2}\)。
-
被计算 6 次,说明有四条直线覆盖。
ABC378F
直接 DFS,当时赛时一眼鉴定为点分治,写了很久,还一直 WA,破防了,最后发现是没有统计分治中心的贡献。
挺水的其实。
ABC380F
暴力题,直接求 SG 函数。
ABC382F
水题,秒错了,火大!
基础线段树区间取 max 练习题。
ABC383F
水题,但是没有秒切。
ABC384F
居然不太会做,赛时没做出来。
题意:
定义函数 \(f(x)\) 表示将 \(x\) 一直除以 \(2\),直到 \(x\) 是一个奇数,这个奇数即为 \(f(x)\) 的值。
给定长为 \(n\) 的序列 \(a\),求 \(\sum_{i=1}^{n}\sum_{j=i}^{n}f(a_i+a_j)\)。
\(1\le n\le 10^{5},1\le a_i\le 10^{7}\)
解法:
假设 \(v\) 的二进制数末尾有 \(x\) 个 \(0\),那么 \(f(v)=v\gg x\)。
考虑计算出二进制末尾至少有 \(k\) 个 \(0\) 的和,容斥一下就能得到二进制末尾恰为 \(k\) 的和。
人机吧,这都不会。
ABC385F
题意:
有 \(n\) 个建筑,第 \(i\) 个建筑在 \(x_i\),高度为 \(h_i\)。求最大的 \(y\) 使得从点 \((0,y)\) 看不到所有建筑的顶端。一个建筑的顶端看不到定义为 \((0,y)\) 和这个建筑顶端的连线经过了其他建筑。
\(1\le n\le 2\times 10^{5}\)
\(1\le X_1\le \cdots\le X_{n}\le 10^{9}\)
\(1\le h_i\le 10^{9}\)
ABC386F
写假了,83 个点只 WA 了 6 个点?要不是被我自己 Hack 了可能一直都是 WA 的。
题意:给定两个串 a 和 b,求经过至多 \(K\) 次如下操作之后能否将 a 串变得与 b 串相同。
-
插入一个字符。
-
删除一个字符。
-
修改一个字符。
字符串长度 \(5\times 10^{5}\), \(1\le K\le 20\)。
解法:
一开始的想法是,设 \(f_{i,j}\) 表示第一个串匹配了前 \(i\) 个字符,用了 \(j\) 次操作,最多能够匹配多少个第二个串中的字符。
然而一直是 WA 的过不去。后来出了一个 hack:
2
aaaaaaab
eaaaaaa
这显然是可以的,但是按照上面的方法做会输出 No。这是因为由于我们希望尽可能匹配长的 b 串,所以 \(f_{1,1}\) 能够匹配长度为 2 的 b 串(先插入一个 e,再顺序匹配第二个 a),但是这样导致最后需要多删除一个字符,导致无法完成。
正确的做法需要考虑此题当字符串长度很小的那个经典做法:设 \(f_{i,j}\) 表示第一个串的前 \(i\) 个字符和第二个串的前 \(j\) 个字符,相等的最小操作次数,发现 \(i\) 和 \(j\) 若相差超过 \(K\),则必然不存在 \(K\) 步以内的方案,所以可以将第二维改成 \(j-i\) 的值,就能在 \(O(nk)\) 的复杂度内正确地完成了。
ABC388F
题意:
有 \(N\) 个格子。给定 \(M\) 个区间 \([L_i,R_i]\),被这些区间覆盖的位置不能经过,其余位置可以通过。从 \(1\) 出发,每一步可以走 \([A,B]\) 个格子。求最后能否到达 \(N\)。
\(2\le N\le 10^{12},0\le M\le 2\times 10^{4},1\le A\le B\le 20\)
保证给定区间递增且互不相交。
解法:
考虑维护能够走到的位置集合,应该是一个区间的形式。假设当前能够走到 \([L,R]\),那么下一步能够走到 \([L+A,R+B]\)。但是这样这两个区间可能有交,所以令新区间的左端点为 \(L'=\max(L+A,R+1)\),这样能够保证每一步之间区间没有交,某一个格子被哪一步的区间覆盖即意味着其到达这个格子的最小步数。
由于 \(A\) 和 \(B\) 很小,容易发现,当非法区间 \(R_i-L_i\) 超过 20 时一定无解。否则将维护的能够走到的区间,与 \([L_i,R_i]\) 的补集取交集即可。
注意到当 \(R-L<A\) 时,新左端点为 \(L+A\),否则为 \(R+1\)。特殊处理 \(A=B\),当 \(R-L<A\) 时,直接暴力将 \(L\) 和 \(R\) 修改为 \(L+A\) 和 \(R+B\)。这样每一次 \(R-L\) 增加 \(B-A\),至多经过 20 次暴力之后 \(R-L\ge A\),此时可以忽略左端点(左端点必定为 \(R-B+1\)),只考虑右端点。这样就能快速得到第一次与给定区间有交的位置了。
ABC388G
题意:
有 \(n\) 个烧饼,每个烧饼有大小。当一个烧饼大小不超过另一个的一半时,这个烧饼可以放在另一个上面,组成饼塔。
给定 \(n\) 个烧饼的大小序列 \(a_i\),\(q\) 次询问,每一次给定 \([l,r]\),问这个区间内的烧饼最多可以组成多少个饼塔。
保证 \(a_i\) 升序!
\(N,Q\le 2\times 10^{5},1\le A_i\le 10^{9}\)。
解法:
对于一个区间,必定是选择某一段等长前缀和后缀,然后从左往右配对。考虑二分答案,拿出前 \(mid\) 个和后 \(mid\) 个,判断是否合法。
容易发现,每一个饼,满足能够堆在其上面的是一段前缀,预处理出能放在其上面的最大位置 \(p_i\)。假设 \(i\) 是后 \(mid\) 个,那么 \(p_i\ge l+mid-1-(r-i)\) 必须满足。移项得到 \(p_i-i\ge l+mid-1-r\),记 \(q_i=p_i-i\),那么只要判断后 \(mid\) 个的 \(q_i\) 的最小值是否满足条件即可。

浙公网安备 33010602011771号