[arc076f]Exhausted? - 贪心
题意:
给你m个椅子可以坐人,初始坐标为正整数1~m,有n个人,每个人希望坐的位置$\leq L_i$或者$\geq R_i$,可以添加若干个椅子在任意的实数位置,求最少要添加多少椅子使得所有人都有位置坐?
$1\leq n,m\leq 2\times 10^5$
$0\leq L_i<R_i\leq 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 }