[arc076f]Exhausted?

题意:

给你m个椅子可以坐人,初始坐标为正整数1~m,有n个人,每个人希望坐的位置$leq L_i$或者$geq R_i$,可以添加若干个椅子在任意的实数位置,求最少要添加多少椅子使得所有人都有位置坐?

$1leq n,mleq 2 imes 10^5$

$0leq L_i<R_ileq m+1$

题解:

这题其实有一个显然的网络流解法,但是直接建图会爆,用线段树优化建图可以过,写的会很麻烦。。。(Orzckw)

场上dalao们八仙过海以不同的姿势各种贪心水到了大量分数。。。

正解是一个优秀的贪心。考虑只有一边的限制(比如只有$L$),那么显然的贪心是,从左到右枚举每个椅子,在$L_i$处决定每个人坐在哪,然后每向后一个椅子就能多放一个,考虑有多少人左端点在当前枚举到的椅子,能放就尽量放,多的就不放,并将空位设为0;

加上$R$的条件其实类似,把每个人记录在$L$上,然后能放就尽量放,遇到放不下的情况时可以考虑用新的这个人代替掉原来的人,条件是他的$R$比原来的人的$R$要大,这样可以保证换出来的人更容易重新放进去。那么用小根堆维护$R$,然后扫一遍即可;

枚举完把放好的人拎到一边,反着做一次只考虑$R$的贪心,即可求出答案。

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 struct task{
 9     int l,r;
10 }a[200001];
11 priority_queue<int>q;
12 pair<int,int>pi[200001];
13 bool cmp(task a,task b){
14     return a.l==b.l?a.r<b.r:a.l<b.l;
15 }
16 int n,m,l,r,tot=0,ans=0,now[200001];
17 int main(){
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
20     sort(a+1,a+n+1,cmp);
21     l=1,r=m;
22     for(int i=1;i<=n;i++){
23         q.push(-a[i].r);
24         if(l<=r&&l<=a[i].l)l++;
25         else{
26             now[++tot]=-q.top();
27             q.pop();
28         }
29     }
30     sort(now+1,now+tot+1);
31     for(int i=tot;i;i--){
32         if(l<=r&&r>=now[i])r--;
33         else ans++;
34     }
35     printf("%d",ans);
36     return 0;
37 }
原文地址:https://www.cnblogs.com/dcdcbigbig/p/9493760.html