不久前的Grakn Forces 2020上,我想出了这个方法,我本来以为这个模型不会很常见。然而,今天的CodeForces #679 Div2上,我第二次碰到了可以用这个模型解决的问题,气人的是,这次我却在代码细节上写挂了,最终掉分,愤而决定当作模板记录下来,以免再犯。
问题
有
算法
首先注意到对于
显然,
当然,在编程中,删除数组中的元素还是太浪费时间了,我们转而把无需删除的有序对加入一个新的数组。只不过,因为我们是从后往前遍历,这样会导致顺序颠倒过来。
这时我们发现,如果我们选了某个

这样一来,我们一共就只有
代码
int minsum(vector<pair<int, int>> &V)
{
if (V.empty())
return 0;
sort(V.begin(), V.end());
vector<pair<int, int>> U{V[V.size() - 1]};
for (int i = V.size() - 2; i >= 0; --i)
if (V[i].second > U[U.size() - 1].second)
U.push_back(V[i]);
int mi = min(U[0].first, U[U.size() - 1].second);
for (int i = 0; i < U.size() - 1; ++i)
mi = min(mi, U[i].second + U[i + 1].first);
return mi;
}
例题
CF1408D:通过计算,可求得每个强盗向上躲过探照灯需走
CF1435C:我们可以得到
INF
)。这相当于是向左扩展和向右扩展。然后套模型。这样我们算出了选固定组每一个数时的最小极差,求一个最小值即可。