1 条题解
-
0
Hall 定理
这是一个关于二分图完美匹配存在性的定理。定理内容如下:将二分图分为左部点 和右部点 ,保证 ,该图存在完美匹配当且仅当对于 ,其中 表示 中与 中点有连边的点的集合。这个可以归纳法证明,感性理解可以参考这篇文章,个人认为写得很生动形象。
我们来看一些例题。
P3488
我将这个题当作 Hall 定理应用的模板题,我会着重解释为什么可以将这个 Hall 定理的形式转化为一个最大子段和。
如果不考虑数据范围,那就是一个二分图最大匹配裸题。但是这数据范围太大,我们不能暴力建边,考虑霍尔定理。我们将脚的大小当作一种类型(左部点), 指脚大小为 的人的个数,右部点是鞋的尺码,也可以将每种尺码的 双鞋都看作在此位置上的 个右部点。取 ,那么只有对于 都满足 才会有完美匹配。现在我们就要使得这个上界最紧。考虑这样一件事,如果我们选择的 并不是一段连续区间,那么假如 ,且 分别满足上界的限制,那么设 ,则,但是 ,因为 和 可能有相同元素。所以我们可以发现,如果取 为一段连续的区间 ,得到的上界一定不松于不连续的 。
于是现在我们讨论 ,那么就是 ,上界就是,
$$\begin{aligned} \sum\limits_{i = l}^{r} num_i &\le k \times (r + d - l + 1) \\ &= k \times d + k \times (r - l + 1) \end{aligned}$$即:
$$\sum\limits_{i = l}^{r} (num_i - k) \le k \times d$$很好,你会发现 是一个定值,所以我们只需要求出最大的 且满足 ,如果这个最大的和 ,那么所有的 都会满足上界条件了,所以就一定存在完美匹配,反之不存在。这是一个简单的线段树维护最大子段和问题,具体可以参考 P4513。
给出丑陋的代码。
#include <bits/stdc++.h> #define ll long long #define lc p << 1 #define rc p << 1 | 1 using namespace std; const int N = 2e5 + 5; int n, m, k, d; namespace SegT{ struct Rinne{ ll lx, rx, ans, sum; friend Rinne operator+(const Rinne a, const Rinne b) { Rinne c; c.sum = a.sum + b.sum; c.lx = max(a.lx, a.sum + b.lx); c.rx = max(b.rx, b.sum + a.rx); c.ans = max(a.rx + b.lx, max(a.ans, b.ans)); return c; } } tr[N << 2]; void pushup(int p) { tr[p] = tr[lc] + tr[rc]; return ; } void build(int p, int l, int r) { if(l == r) { tr[p].sum = -k, tr[p].ans = tr[p].lx = tr[p].rx = 0; return ; } int mid = (l + r) >> 1; build(lc, l, mid), build(rc, mid + 1, r); pushup(p); return ; } void modify(int p, int l, int r, int x, int v) { if(l == r && l == x) { tr[p].sum += v; tr[p].ans = tr[p].lx = tr[p].rx = max(tr[p].sum, 0ll); return ; } int mid = (l + r) >> 1; if(x <= mid) modify(lc, l, mid, x, v); else modify(rc, mid + 1, r, x, v); pushup(p); return ; } void modify(int x, int v) { modify(1, 1, n, x, v); } } using namespace SegT; int main() { scanf("%d %d %d %d", &n, &m, &k, &d); ll lim = 1ll * k * d; build(1, 1, n); for (int i = 1; i <= m; ++i) { int x, v; scanf("%d %d", &x, &v); modify(x, v); if(tr[1].ans <= lim) puts("TAK"); else puts("NIE"); } return 0; }
- 1
信息
- ID
- 2788
- 时间
- 4000ms
- 内存
- 128MiB
- 难度
- 9
- 标签
- 递交数
- 12
- 已通过
- 7
- 上传者