arc076 F - Exhausted? (霍尔定理学习)

参考了这篇大佬的博客

【题意】

有$$$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 }

猜你喜欢

转载自www.cnblogs.com/tobyw/p/9347092.html