多校联训分治专题

[ICPC2017 WF]Money for Nothing

因为赚取的差价就是等于时间之差与价格之差的乘积。

所以可以看成是平面上的问题。

建立一个直角坐标系,将时间作为横坐标,价格作为纵坐标。

然后将生产商和消费商的信息转为平面上的点,其中将生产商划为A类点,消费商划为 \(B\) 类点。

之后问题就成了在平面上 左下角为 \(A\) 类点 右上角为 \(B\) 类点 求最大的矩阵面积的问题。

先将 \(A\) 类点按坐标进行排序。

如果 \(A\) 类点其中的两点出现了上图的情况。

显然,由 \(a_1\) 点为左下角的矩阵一定不会比以 \(a_2\) 点为左下角的矩阵的面积更大。

所以可以排除 \(a_1\) 点,将 \(a_1\) 点从候选集合中删去。

之后是将 \(B\) 类点按坐标进行排序。

如果 \(B\) 类点其中的两点出现了上图的情况。

同样,由 \(b_1\) 点为右上角的矩阵一定不会比以 \(b_2\) 点为右上角的矩阵的面积更大。

所以我们可以将 \(b_1\) 点从候选集合中删去。

我们发现在排除所有无用的点之后,\(A\) 类点和 \(B\) 类点都呈现出 \(x\) 递增 \(y\) 递减的样子。

考虑优化:

在去除无用点后的任意两个 \(A\) 类点和任意两个 \(B\) 类点中。

\(a_1,b_2\) 围成的矩形是以 \(a_1\) 为左下角的矩形当中最大的那一个。

我们可以得到这样一个结论:

\(a_2\)\(b_1\) 围成的矩形的大小一定小于 \(a_2\)\(b_2\) 围成的矩形的大小。

由此我们就可以用决策单调性来优化,复杂度 \(O(n\log n)\)

点击查看代码

Gym 103202L Forged in the Barrens

#592. 新年的聚会

首先有一个结论:

对于一张 \(n\) 个点 \(m\) 条边的无向图,可以将点集划分为 \(O(\sqrt m)\) 个独立集

证明:

对于度数 \(≥\sqrt m\) 的点,每个点单独作为一个独立集。

对于度数 \(<\sqrt m\) 的点,设每个点所属的独立集编号为 \(t_i\)(从 \(1\) 开始),那么 \(t_i≤\sqrt m\)

于是独立集个数就是 \(O(\sqrt m)\) 的。

然后我们可以考虑快速找到两个集合 \(A,B\) 之间的边:

\(A\) 均匀分成两个集合 \(A1,A2\)\(B\) 均匀分成 \(B1,B2\),然后判断 \(A1∪B1,A2∪B1,A1∪B2,A2∪B2\),如果当前并集并非独立集,那么就递归下去求解。

显然,整个递归树的深度是 \(\log n\) 的,于是我们用 \(\log n\) 的代价找到了一条边,于是询问复杂度就是 \(O(m\log n)\) 的。

点击查看代码

CF1442D Sum

容易发现最终至多一个取了一部分的数组,其它要么完全取完,要么完全没有动过。

分治做背包,枚举是哪个物品只取了一部分,取最大值即可。

点击查看代码

CF1553H XOR and Distance

首先考虑一个真暴力,要求异或 \(x\) 之后的最小差,我们就建出原序列的 \(\text{Trie}\) 树,遍历整棵 \(\text{Trie}\)。对于每个分叉点(即,有两个儿子的点),我们在与 \(x\) 这一位相同的那一边查询异或最大值 \(mx\),不同的那一边查询异或最小值 \(mn\),再用 \(2^d+mn-mx\) 更新答案(\(d\) 是当前这条边在 \(\text{Trie}\) 上的深度)。

假如不对于每个 \(x\) 分别建 \(\text{Trie}\) ,从低位到高位枚举 \(x\) ,依次在原有 \(\text{Trie}\) 树上反转对应位的节点,\(\text{Trie}\) 树上深度为 \(d\) 的节点最多有 \(2^d\) 个,每个点有 \(2^{K-d}\) 次可能的询问,这样总复杂度为:

\[O(\sum_d2^d2^{K-d})=O(2^KK) \]

点击查看代码

CF343E Pumping Stations

注意到问题与任意两点在原图上的最小割相关,所以建出最小割树。

\(d(i, j)\) 表示节点 \(i,j\) 在最小割树上的简单路径经过的所有边的边权的最小值,问题转化为求一个 \(n\) 阶排列 \(p_1, p_2, \cdots, p_n\) ,最大化 \(f(p) = \sum\limits_{i = 1} ^ {n - 1} d(p_i, p_{i - 1})\)

由于 \(d(i, j)\) 是边权最小值的形式,所以我们猜测答案上界就是所有边的边权和。考虑构造。

找到整棵树上边权最小的边 \((u, v)\),设它把树分成 \(S, T\) 两个点集。

考虑最终的排列。如果 \(u\to v\) 这条边被经过超过一次,通过调整法容易证明不优,因此,我们断言必然存在最优排列使得 \(u\to v\) 只被经过一次,即必然是先完整地走完 \(S\),再从 \(S\) 中的某个点以 \(w(u\to v)\) 的贡献走到 \(T\) 中的某个点,再完整地走完 \(T\)

跨过 \(u, v\) 的这次移动 \(p_i\to p_{i + 1}\) 最小值已经是 \(w(u\to v)\) 了,所以无论 \(p_i\)\(S\) 内部的哪个点,\(p_{i + 1}\)\(T\) 内部的哪个点,都不会影响到 \(d(p_i, p_{i + 1})\)

这样,我们将问题划分成了在 \(S\)\(T\) 内部的子问题,递归边界即点集内部只剩下一个点,此时直接输出它的编号即可。

时间复杂度是构建最小割树的复杂度,加上构造的复杂度 \(O(n^3m+n ^ 2)\)

点击查看代码

CF1179E Alesya and Discrete Math

考虑分治,每次将其分成两部分

左边:自变量取值范围 \([0,x]\) ,因变量取值范围 \([0,\frac{L}{2}]\)

右边:自变量取值范围 \([x,10^{18}]\) ,因变量取值范围 \([\frac{L}{2},L]\)

然后递归下去分治即可。

考虑如何求出 \(x\) ,对于所有的 \(f_i\) ,求出使得 \(f_i(x_i)=\frac{L}{2}\)\(x_i\) 。因为函数取值单调不降,这里用一个二分查找即可,查询一次所需询问次数是 \(\log 10^{18}=60\) 次。(因为在 \(O\) 里带常数不太好,以下用 \(T\) 表示 \(\log 10^{18}\))。

然后可以找出 \(x\) 的中位数,分析一下这一部分的复杂度:

求出使得 \(f_i(x_i)=\frac{L}{2}\)\(x_i\) 的复杂度是 \(O(T)\) ,递归 \(O(\log n)\) 层,每层对所有的 \(f_i\)\(x_i\) 都需要 \(O(T)\)

总次数大概是 \(O(n\cdot T\cdot\log n)\approx 6\cdot 10^5\)

但是无法通过,我们需要进行优化,考虑 \(\text{kth_element}\) 的方法,随机选择一个函数,二分出它的 \(x\) ,再将其它函数与这个 \(x\) 比较,期望递归 \(\log\) 层,总操作次数 \(O(T\log n+n)\)

下面分析时间复杂度:

\(n=2^s\) ,那么 \(i\) 层分治之后,段数是 \(2^i\) ,每段长度是 \(2^{s-i}\)

对于每段找中位函数所需的询问次数就是 \(O(T(s-i))\)

对于全部的寻找中位函数,总共需要

\[O(\sum\limits_{i=1}^{s} T(s-i)2^i)=O(T\sum\limits_{i=1}^{s} (s-i)2^i)=O(T\sum\limits_{i=1}^{s} n\frac{s-i}{2^{s-i}})\\ =O(nT\sum\limits_{i=1}^{s} \frac{s-i}{2^{s-i}})=O(nT)\text{次} \]

总复杂度是 \(O(n\log n+Tn)\)

点击查看代码

CF865F Egg Roulette

posted @ 2022-06-12 19:55  一粒夸克  阅读(100)  评论(0编辑  收藏  举报