Codeforces VP/补题小记 (持续填坑)

Codeforces VP/补题小记

1149 C. Tree Generator

给你一棵树的括号序列,每次交换两个括号,维护每次交换之后的直径。

​ 考虑括号序列维护树的路径信息和,是将左括号看做 \(-1\) ,右括号看做 \(1\) ,那么一段竖直向上的路径可以表示为括号序列的一个区间和,一段竖直向下的路径可以看做括号序列的一个区间和的相反数。我们要维护的是树的直径,也就是一段连续的和减去紧随其后的一段连续的差。具体来说就是

\[\max_{\forall [l,r]}\{\sum_{i=l}^kw[i]-\sum_{i=k+1}^r w[i]\} \]

​ 可以简单的证明如果选取的区间不能代表树上的路径,取到的式子的和一定不是最优解,线段树维护这个式子即可。维护起来略有麻烦,类似于维护区间最大子段和,更新的时候需要多记几个信息。复杂度 \(\mathcal O (n\log n)\)

1149 D. Abandoning Roads

\(n\) 个点 \(m\) 条边且仅有两种边权 \(a, b (a<b)\) 的无向简单图 \(G\)\(\forall i\) 求出 \(G\) 的所有最小生成树中,\(1-i\) 的路径的最小长度。\(1\leq n\leq 70,n-1\leq m \leq 200\)

​ 这个题我一开始想了一个错误的做法,先求出最小生成树中 \(b\) 边的数量记为 \(k\) ,然后分别求出 \(1\) 到各个点经过不超过 \(k\)\(b\) 边的最短路。这个做法的错误之处在于,虽然可以证明起始端点都在路径上的 \(a\) 边不会环切掉路径上的 \(b\) 边,但是只要令始端点在路径上就能环切了。

​ 期间我还考虑了另外一种做法,后来得知后一种思路是可以扩展到正解的。考虑将所有 \(a\) 边缩成若干个联通块,不难证明,如果一条生成树的路径离开了一个联通块后又进入了这个联通块,这棵生成树一定不是最小生成树,因为其选择了会被环切的 \(b\) 边。此时直接大力状压 \(dp\) 的复杂度是 \(O(2^nm)\) 的。

​ 再往下分析,如果一个联通块大小 \(\leq 3\) ,那么即使存在离开这个联通块后又来到这个联通块的路径,这条路径也必然不是最短路,因为这样联通块内部最长的边是 \(2a\) ,而做上述操作需要 \(2b\) 。所以可以直接忽视掉所以大小 \(\leq 3\) 的联通块的限制,复杂度优化到 \(\mathcal O (2^{\frac{n}{4}}m)\)

1168 C. And Reachability

有一个长度为 \(n\) 的序列 \(A\) , \(i,j\) 之间有一条有向边当且仅当 \(i < j, A[i] \text{ and } A[j] > 0\) ,每次给出 \(x, y(x<y)\) ,询问从 \(x\) 出发是否能到达 \(y\)

​ 按位考虑,对于当前数 \(A[x]\) ,其能直接到达后面所有和其有共同位的数。显然,对于每一位,较前面的数能到达较后面的数,所以只需要维护每一个数 \(A[x]\) 其能到达某一位有 \(1\) 的最前面的数的位置即可。最后判断 \(A[y]\) 的某一位 \(1\) 是否能被 \(A[x]\) 在其之前到达。复杂度 \(\mathcal O(n\log^2 n)\)

1168 D. Anagram Paths

有一棵二叉树,每条边上有小写字母或者 \('?'\) ,每次修改一条边上的字符,要求维护所有叶子到根的路径上的 \('?'\) 填为任意小写字母后是否能重排达到一致, 如果可以,还需输出每种字符的最大可能出现次数。

​ 首先如果所有叶子深度不相等,无论怎么更改边上的字符都是无解。

​ 然后令 \(f[x][c]\) 表示所有 \(x\) 子树内的叶子到 \(x\) 的路径上字符 \(c\) 的数量最大值,\(len[x]\) 表示 \(x\) 到叶子的距离。

我们可以归纳证明,能够重排达到一致当且仅当

\[\forall x \sum_{c} f[x][c]\leq len[x] \]

​ 考虑当 \(x\) 是叶子时候,显然充要。对于任意非叶子节点 \(x\),假设其子树内所有点都满足条件,此时必要性显然。充分性考虑先将原先的所有路径排好,对于新加进来的边,如果是一条,则必然合法。如果是两条边,要满足式子必须改变的 \(f[x][c]\) 数量 \(<2\) ,此时另一边会有多出来的问号填上这个字符。

​ 直接暴力维护 \(f[x][c]\) 复杂度是 \(O(nq)\) 的,但是之前的证明启发我们,对于只有一个孩子的节点,可以直接将该节点与孩子合并不影响答案。然后这里有一个二叉树的小套路,如果这样合并,二叉树的深度不超过 \(\mathcal O(\sqrt n)\)

​ 证明,如果二叉树不存在只有一个儿子的节点,那么第 \(i\) 层的深度一定要大于第 \(i-1\) 层的深度,此时深度最多为 \(\mathcal O(\sqrt n)\) ,这样直接暴力修改 \(dp\) 值即可,复杂度 \(\mathcal O(q\sqrt n)\)。当然直接动态 \(dp\) 也是可以的。

1188 D. Make Equal

有一个序列 \(a\) ,每次可以花费 \(1\) 的代价将其中一个数加上 \(2\) 的幂次,求将所有数变成相等的数时所需的最少代价。

​ 先将 \(a\) 从小到大排序,若我们将 \(a_n\) 最终加上了 \(S\) ,则 \(a_i\) 最终加上了 \(S+a_n-a_i\) 。那么问题转化为选择一个数 \(S\) ,最小化 \(\sum_{i=1}^n bit(S+a_n-a_i)\)

​ 考虑按位 \(dp\) 决策 \(S\) 的每一位选 \(0\) 还是选 \(1\) ,因为最终要处理的贡献是等于 \(a_n-a_i, S\) 这一位数相加以及上一位的进位决定的,我们还需要记录哪些数在当前状态下被进位了。可以发现,假设考虑到了前 \(k\) 位,当前位会进位的数一定是按照 \(\mod 2^k\) 排序结果下的一个后缀,\(dp\) 的时候记录一下这个后缀的长度即可,复杂度 \(\mathcal O (n\log n)\)

1098 D. Eels

鱼缸里有一些鱼,鱼有一个属性值 \(w_i\) ,两条鱼 \(i,j(w_i < w_j)\) 可能会合并为一条新的鱼 \(w_i+w_j\) ,如果一次合并的过程中有 \(2w_i\geq w_j\) ,那么称这一次合并是危险的。现在要动态加入删除鱼,维护如果开始一系列的合并,最多可能发生的危险合并次数。

​ 打表发现发生危险合并最多的方式一定是每次取出当前两条最小的鱼进行合并,然后考虑怎么维护这个东西。考虑将当前所有鱼按照 \(w_i\) 排好序,当一条鱼满足 \(w_i > 2\sum_{j=1}^{i-1} w_j\) 时,这条鱼被取出的时候显然不会发生危险的合并。现在我们证明,除此之外的所有鱼被取出的时候,都会发生危险的合并。反证,假设取出的是两条鱼 \(x=w_a+w_b,y=w_c+w_d(2x< y)\) ,即 \(w_a+w_b<w_d\) ,也就是说 \(x\) 会先与 \(w_c\) 合并,不存在这样的两条鱼。那么我们只要动态维护

\[\sum_{i=1}^{n}[w_i > 2\sum_{j=1}^{i-1} w_j] \]

用一个维护权值时候的小技巧,将其划分成 \(\log\) 个块,第 \(i\) 个维护权值在 \([2^{i-1},2^i)\) 间的所有鱼,此时,每个块内只有最小值可能产生贡献,用堆来维护这个最小值可以做到 \(\mathcal O(n\log n )\) 的复杂度。

1083 C. Max Mex

有一棵树,树上的节点权值是一个 \(0\)\(n-1\) 的排列,现在动态交换两个节点的权值,要求维护树上所有路径的 \(\text{mex}\) 的最大值。

​ 假设答案是 \(k\) ,那么其合法的充要条件是 \(0-1,1-2,..,(k-1)-k\) 这些路径组成的并仍然是一条路径,我们用线段树维护一个区间内的路径的并的端点,然后在线段树上二分答案,预处理 \(lca\) 复杂度为 \(\mathcal O(n\log n)\)

1158 D. Winding polygonal line

平面上有 \(n\) 个点,要求找一个排列,满足相邻连线后不自交,且用一个字符串限制了第 \(i\) 步必须要左转/右转。\(n \leq 2000\) ,保证不存在三点共线的情况。

​ 考虑每次找出在凸包上的任意一个点,其下一个点选择在凸包上左边/右边的点,剩下的点仍然组成一个凸包,且根据凸包的性质,之前选择的点一定不再剩下的点组成的凸包内,这样子分步构造即可,复杂度 \(\mathcal O(n^2)\)

704 D. Captain America

平面上有 \(n\) 个点,每个点必须涂成红色和蓝色中的一种,花费各为 \(r\)\(b\) 。需要满足 \(m\) 条限制,每条限制形如 \(y=b\) 这条直线上两种颜色的点的数目之差的绝对值不能超过 \(d\)\(x=b\) 这条直线上两种颜色的点的数目之差的绝对值不能超过 \(d\),要求判断是否有解,如果有解还需要最小化花费。\(n,m \leq 10^5\)

​ 先考虑判断是否有解, 假设某一行的限制为 \(d\) ,一共有 \(k\) 个点,选了 \(x\) 个红点,满足条件即

\[|2x-k|\leq d \\ -d \leq 2x-k \leq d \\ \dfrac{k-d}{2}\leq x \leq \dfrac{k+d}{2} \]

​ 对于列的限制同理,考虑经典的二分图建模,每一个点选红色就让对应行的点和对应列的点连边,那么源点连向行的边和列连向汇点的边就是上面的上下界限制,存在可行流即有解。最小化花费即最大化花费较小的那种颜色的点数,在可行流基础上跑最大流即可。

1305 D. Kuroni and the Celebration

给定一棵 \(n\) 个节点的有根树,边以双向边的形式给出,每次可以询问两个节点 \((u, v)\)\(lca\) ,要求在不超过 \(\lceil\frac{n}{2}\rceil\) 次询问的情况下找出树的根,\(n \leq 3500\)

​ 每一次询问如果 \(u,v\)\(lca\) 不是 \(u,v\) 中任意一个节点的话那么能排除两个节点,否则只能排除一个,所以要求每一次询问的结果不是本身,考虑任意一颗节点数 \(> 1\) 的树都至少有两个度为 \(1\) 的节点,每次拿这两个节点出来询问即可。特别的,如果返回结果是其中一个节点,那么这个节点一定是根,这里几步的证明比较简单,省略。

1305 E. Kuroni and the Score Distribution

要求构造一个长度为 \(n\) 的序列,\(a_1,a_2,...,a_n\) ,满足 \(a_i+a_j=a_k,i<j<k\) 的对数恰好为 \(M\)\(a_i \leq 10^9\)

​ 考虑一个序列 \(1,2,3,4,...,n\) 的贡献是 \(\sum_{i=1}^n \lfloor\frac{i-1}{2}\rfloor\) ,不难证明这是所有长度为 \(n\) 的序列中贡献最大的。如果要求的贡献大于这个值,就不可能构造出来。除此之外,先不考虑要求的长度,我们可以用一个长度为 \(m,m \leq n\) 的序列构造出要求的贡献,具体来说当序列变成 \(1,2,3,4,...,m-1,m+2k\) 时,贡献会比 \(1,2,3,4...,m-1,m\) 恰好减少 \(k\) ,那么我们可以容易得到 \(m,k\) ,而对于长度不够的部分只需要加一段不可能与之前的序列以及内部产生贡献的序列即可,这样的序列构造比较简单,省略。

1305 F. Kuroni and the Punishment

有一个长度为 \(n\) 的正整数序列 \(a\) ,每次可以花 \(1\) 的代价使 \(a_i +1\) 或者 \(-1\) ,求使整个序列 \(\gcd>1\) 需要花费的最少代价。 \(n \leq 3 \times 10^5\)

​ 如果让最终答案所用的 \(\gcd =2\) 的话,所需要的花费就是 \(M=\sum_{i=1}^n a_i \bmod 2\) ,这里有 \(M\leq n\) ,那么可以用反证法证明至少有一半的数的操作次数 \(\leq 1\) 。考虑随机选取 \(x\) 个数,对于每一个选取出来的数 \(k\) ,将 \(k-1,k,k+1\) 三个数的所有质因数分别作为答案所用的 \(\gcd\) 计算一遍答案,这样的错误概率是 \(\frac{1}{2^x}\)\(x\)\(20\) 以上就没什么问题了。

1305 G. Kuroni and Antihype

有一张无向图,\(i\)\(j\) 有边当且仅当 \(a_i \and a_j = 0\) ,每次可以选择一个没加进集合的点加进集合,或者选择一个集合中的点 \(x\) ,以及一个与 \(x\) 相邻且没有加进集合的点 \(y\) ,将 \(y\) 加进集合并获得 \(a_x\) 的收益,求将所有点加入集合的最大收益。 \(n \leq 3 \times 10^5\)

​ 如果图已经建出来了,那么最终答案的形态一定是一个外向树森林,即先选 \(x\) 再选 \(y\) 的话会有一条有向边,强行为这个森林添加一个根节点的话就会变成一棵外向树,考虑一棵外向树对答案的贡献,每一个节点恰有一条入边,度数 \(- 1\) 条出边,所以每一个节点对答案的贡献是 \(a_i \times (deg_i-1)\) ,把点的贡献转换到边上,每一条边 \(x, y\) 的贡献就是 \(a_x+a_y\) ,这样每个点的贡献算了度数次,最后再减去 \(\sum_i a_i\) 就是答案,问题转化为求一个最大生成树。

​ 首先可以证明整张图的边数不超过 \(3^{18}\) ,因为 \(\sum_{S=0}^{2^n}1+\sum_T[T\subseteq S]=3^n\) ,可以用子集枚举的方法把图建出来,用 \(\text{Bruvuka}\) 算法的话,可以用 \(\text{FMT}\) 做到 \(\mathcal O(n2^n)\) 的复杂度。

1316 F. Battalion Strength

有一个大小为 \(n\) 的集合 \(A\),对于 \(A\) 的任意一个子集 \(a\) 的贡献为将 \(a\) 排序后 \(\sum_{i=1}^{|a|-1}a_ia_{i+1}\) ,进行 \(q\) 次修改,每次修改 \(A\) 中的一个元素的值,每次修改后需要输出 \(A\) 所有子集的贡献和。 \(n,q \leq 3\times 10^5\)

​ 将序列排序后,每一对数 \((a_x,a_y), x \leq y\) 的贡献数 \(2^{x-y-1} a_xa_y\) ,由于要动态修改,可以用线段树上分治的思想统计,对于一个线段树节点上的区间,统计跨过区间的点对的贡献,维护区间节点数 \(sz_i\) ,将这个区间视为左边的区间时的 \(\sum 2^ia_i\) ,视为右边区间时的 \(\sum 2^{-i} a_i\) ,统计的时候额外乘上 \(2^{-sz_i}\) 即可。每次修改修改两个叶子的值。

1322 B. Present

有一个长度为 \(n\) 的序列 \(a\) ,求所有无序数对 \(x, y(x<y)\)\((a_x+a_y)\) 的异或和,\(n \leq 4 \times 10^5\)

​ 考虑最终答案每一位是否有 \(1\) ,也就是统计 \(a_x+a_y\) 在这一位有 \(1\) 的对数,假设这一位是 \(2^k\) ,那么一对相加在这一位有 \(1\) 当且仅当 \((a_x \bmod 2^{k+1})+(a_y \bmod 2 ^{k+1})\in[2^{k},2^{k+1})\or[2^{k+1}+2^k,2^{k+2}-1)\) 排序后用二分即可统计出来,如果用归并和 \(\text{twopointers}\) 的话可以减少掉一个 \(\log\) 的复杂度。

1322 C. Instant Noodles

有一张左右各 \(n\) 个点,\(m\) 条边的二分图,对于每一个右边的点有一个点权,对于左边点的一个集合,其权值为右边与其相邻的点的点权之和,求所有左边点集合点权的 \(\gcd\)\(n,m\leq 5 \times 10^5\)

​ 一个简单的问题是,对于 \(n\) 个数求它们所有子集的 \(\gcd\),这个东西等价于求这 \(n\) 个数的 \(\gcd\) ,因为一个数整除一个这个集合中的每一个数,一定能整除这些数的和。然后对于原问题,与左边的点连边情况的右边点是必须同时选同时不选的,否则右边的点是独立的,那么将这类点合并起来,用它们的和代替它们,再求所有数的 \(\gcd\) 就是答案。

1290 B. Irreducible Anagrams

给出一个字符串 \(s\)\(q\) 次询问,每次给出一个区间 \([l,r]\) ,问是否存在一个字符串 \(t\) ,使得 \(s[l:r], t\) 是 Irreducible Anagrams, \(q, |s| \leq 2\times 10^5\)

​ 首先 \(|s[l:r]|=1\) 一定无解,然后考虑如果这个字符串首尾字符不同,那么我们一定可以构造一个字符串 \(t\) ,让 \(t\) 为当前字符串首尾字符互换后的字符串即合法。其次,如果字符串拥有至少三种字符,也一定不合法,假设此时首尾相同只需要选取两个与首尾不同的字符,将位置靠后的与首交换,将位置靠前的与尾交换即可。然后可以简单证明除此之外的情况一定无解。

1290 C. Prefix Enlightenment

给定一个长度为 \(n\) 的 01 串 \(S\),和 \(k\)\(S\) 的下标子集,且任意三个子集的交集为空集。一次操作可以选择一个子集,将子集中的下标对应的 \(S_i\) 取反。令 \(m_i\) 为让 \(S_{1 \sim i} = 1\) 的最少操作次数,求出所有的 \(m_i\),保证有方案。\(1 \leq n,k \leq 3 \times 10^5\)

​ 任意两个子集交集为空集说明了任意一个元素只会出现在至多 \(2\) 个集合中,那么对于这两个集合,在这一位要求为 \(1\) 的时候,要么同时选或者同时不选,要么只能选一个。

​ 考虑用种类并查集维护这种关系,每一个集合 \(x\)\((x,0)\) 表示选这个集合,\((x,1)\) 表示不选这个集合,那么对于初始为 \(0\) 的位置对应的两个集合 \((x,y)\) ,合并 \((x,0),(y,1)\)\((x,1),(y,0)\) 。对于初始为 \(1\) 的位置对应的两个集合,合并 \((x,0),(y,0)\)\((x,1),(y,1)\) 。这里维护了集合之间的选取关系,即对联通块中的任意集合进行了对应操作,联通块内的所有集合都必须要按照其在联通块里的状态操作。然后要维护每一时刻对于前 \(i\) 种元素对应集合都操作过的最小花费,只需要先撤销原先的贡献,再加上两种操作中花费较小的即可。而对于强制选或者不选某集合的情况,可以用一个权值无限大的虚拟点来处理。

CF1290D Coffee Varieties (hard version)

给定正整数 \(n,k\)。有 \(n\) 个数 \(a_1,a_2,\dots,a_n\)初始未知,有一队列 \(Q\) 初始为空。

每次查询你可以给出一个编号 \(x\),交互系统会依次进行如下操作:

  • 告诉你当前 \(Q\) 中是否有与 \(a_x\) 相同的数
  • \(a_x\) 放入 \(Q\) 的尾部
  • 如果此时 \(Q\) 中元素多于 \(k\) 个,弹出队首元素

此外,你还可以重置队列,这将使得 \(Q\) 中所有元素被弹出。重置队列不算入查询次数。

现请你求出 \(a_1,a_2,\dots,a_n\)中有多少个不同的数。要求你的查询次数不超过 \(\frac{3n^2}{2k}\),重置次数不超过 \(30000\)

保证 \(n,k\)\(2\) 的整数次幂,并且 \(\frac{3n^2}{2k}\le 15000\)

​ 比较容易的想法是先将数分成 \(\frac{2n}{k}\) 块,这样可以用 \(k\) 次操作去除两个块内的重复元素,然后发现当 \(x\)\(y\) 这两个块比较后,再拿 \(y\)\(z\) 比较的操作次数只有 \(\frac{k}{2}\) 次,由于每一个块都要和其它所有块去重,相当于一个 \(\frac{2n}{k}\) 的完全图,每次可以花链长 \(\times \frac{k}{2}\) 的代价删掉一条链,我们知道完全图在点数为偶数时有一个经典构造可以每次删掉一条长度为 \(n\) 的链,那么总代价就是 \(\frac{2n}{k}\times \frac{k}{2} \times n=\frac{n^2}{k}\)

posted @ 2019-09-15 14:04  Joyemang33  阅读(552)  评论(0编辑  收藏  举报