Description:
個人,每個人可以選 和 的位置坐下,問最少有多少個人沒有位置。
Solution:
根據 定理,我們有最大匹配
所以最少人數即爲 ,枚舉右端點,線段樹維護左端點即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;
int n, m, ans;
int tag[maxn * 4], mx[maxn * 4];
pair<int, int> a[maxn];
void pushdown(int x) {
if(tag[x]) {
tag[x << 1] += tag[x];
tag[x << 1 | 1] += tag[x];
mx[x << 1] += tag[x];
mx[x << 1 | 1] += tag[x];
tag[x] = 0;
}
}
int query(int l, int r, int x, int a, int b) {
if(l > b || r < a) {
return 0;
}
if(l >= a && r <= b) {
return mx[x];
}
pushdown(x);
int mid = (l + r) >> 1;
return max(query(l, mid, x << 1, a, b), query(mid + 1, r, x << 1 | 1, a, b));
}
void update(int l, int r, int x, int a, int b, int d) {
if(l > b || r < a) {
return;
}
if(l >= a && r <= b) {
mx[x] += d;
tag[x] += d;
return;
}
pushdown(x);
int mid = (l + r) >> 1;
update(l, mid, x << 1, a, b, d);
update(mid + 1, r, x << 1 | 1, a, b, d);
mx[x] = max(mx[x << 1], mx[x << 1 | 1]);
}
void build(int l, int r, int x) {
if(l == r) {
mx[x] = -m + r - 1;
return;
}
int mid = (l + r) >> 1;
build(l, mid, x << 1);
build(mid + 1, r, x << 1 | 1);
mx[x] = max(mx[x << 1], mx[x << 1 | 1]);
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &a[i].first, &a[i].second);
}
sort(a + 1, a + n + 1);
build(1, m + 1, 1);
for(int i = 0, j = 1; i <= m; ++i) {
while(j <= n && a[j].first <= i) {
update(1, m + 1, 1, 1, a[j].second, 1);
++j;
}
ans = max(ans, query(1, m + 1, 1, i + 1, m + 1) - i);
}
printf("%d\n", max(ans, n - m));
return 0;
}