参考了这篇大佬的博客
【题意】
有$$$m$$$个座位,分别位于坐标为$$$1, 2, 3, ..., m$$$的地方;$$$n$$$个客人,第$$$i$$$位客人只坐位于$$$[0, Li]\cup[Ri, \infty]$$$的座位。每个座位只能坐一个人,问最少需要添加几个座位才能使所有人坐下?
【分析】
霍尔定理说的是,已知点集$$$X=\{x_1, x_2, ..., x_n\}, Y=\{y_1, y_2, ..., y_m\}$$$,和边集$$$E$$$,其中每条边都是连接X与Y中的一个点,能否存在一个方案,利用Y中的n个点和E中的n条边,使得这些点与X中的点一一对应。霍尔定理不是求出可行方案的办法,但给出了存在一个可行的方案的充分必要条件——对任何一个大小为$$$k$$$的$$$X$$$的子集,在$$$Y$$$中至少有$$$k$$$个点经过$$$E$$$中的边与它们相连。
【代码】
1 #include <stdio.h> 2 #include <vector> 3 using std::vector; 4 5 #define N_max 200005 6 7 #define left(x) ((x)<<1) 8 #define right(x) (((x)<<1)|1) 9 #define mid(l,r) (l+((r-l)>>1)) 10 #define max(a,b) ((a)>(b)?(a):(b)) 11 int lch[N_max << 2], rch[N_max << 2], lzy[N_max << 2], val[N_max << 2]; 12 13 inline void lzydown(int cur) 14 { 15 if(lzy[cur]) 16 { 17 int l = left(cur), r = right(cur); 18 lzy[l] += lzy[cur]; 19 lzy[r] += lzy[cur]; 20 val[l] += lzy[cur]; 21 val[r] += lzy[cur]; 22 lzy[cur] = 0; 23 } 24 } 25 26 inline void updup(int cur) 27 { 28 val[cur] = max(val[left(cur)], val[right(cur)]); 29 } 30 31 void build(int cur, int cl, int cr) 32 { 33 lch[cur] = cl; rch[cur] = cr; 34 if (cl == cr) { 35 val[cur] = cr; 36 return; 37 } 38 int m = mid(cl, cr); 39 build(left(cur), cl, m); 40 build(right(cur), m + 1, cr); 41 updup(cur); 42 } 43 44 void add(int cur,int cl,int cr) 45 { 46 if(lch[cur]==cl&&rch[cur]==cr) 47 { 48 lzy[cur]++; 49 val[cur]++; 50 return; 51 } 52 lzydown(cur); 53 int m = mid(lch[cur],rch[cur]); 54 if (cr <= m) 55 { 56 add(left(cur), cl, cr); 57 } 58 else if(cl>m) 59 { 60 add(right(cur), cl, cr); 61 } 62 else 63 { 64 add(left(cur), cl, m); 65 add(right(cur), m + 1, cr); 66 } 67 updup(cur); 68 } 69 70 int query(int cur,int cl,int cr) 71 { 72 if (lch[cur] == cl&&rch[cur] == cr) 73 { 74 return val[cur]; 75 } 76 int m = mid(lch[cur], rch[cur]); 77 lzydown(cur); 78 if (cr <= m) 79 { 80 return query(left(cur), cl, cr); 81 } 82 else if (cl>m) 83 { 84 return query(right(cur), cl, cr); 85 } 86 else 87 { 88 int ql= query(left(cur), cl, m); 89 int qr= query(right(cur), m + 1, cr); 90 return max(ql, qr); 91 } 92 return -1; 93 } 94 95 vector<int> ipt[N_max]; 96 int ans = 0; 97 int main() 98 { 99 int n, m; 100 scanf("%d %d", &n, &m); 101 ans = max(0,n - m); 102 int a[2]; 103 for(int i=0;i<n;++i) 104 { 105 scanf("%d %d", a, a + 1); 106 ipt[a[0]].push_back(a[1]); 107 } 108 build(1, 0, m + 1); 109 for(int l=0;l<=m;++l) 110 { 111 int sz = ipt[l].size(); 112 for(int t=0;t<sz;++t) 113 { 114 int r = ipt[l][t]; 115 add(1, 0, r); 116 } 117 int temp = query(1, l + 1, m + 1) - m - l - 1; 118 ans = max(ans, temp); 119 } 120 printf("%d", ans); 121 return 0; 122 }