Description
Solution
额外的椅子可以放置在任意实数位置,所以该问题其实就问最多能够有多少人坐下。
由于每个人的需求有<=l和>=r两个限制,并不是很好下手,我们先考虑一个限制的情况(贪心)。
我们把所有的需求按照l排序。然后从1到m枚举椅子,记录一个empty(即目前1-i位的空位数)。枚举到i的时候考虑将所有lj=i需求加入,每加入一个empty--。如果empty为0,并且目前坐了椅子的人中有某一个人k需求的rk比rj要小,则可以用j的信息替换k(因为在后续枚举r的时候k坐下的概率比j大)。这里需要用优先队列记录当前坐了椅子的人的最小值,进行替换即可。
之前处理l的时候需要把没有坐下的人记录下来,然后通过empty值知道目前的空位为m-empty+1到m,直接排序枚举即可。
正确性:如果一个人没有坐下,要么是因为它的l=0,r=m+1,根本没有合适位置;要么是因为在枚举r的时候空位不够了。我们在枚举l,将1-某个数的椅子填满的时候已经把所有尽量小的r剩下来了,如果在这种情况下都没有空位,那是无论如何都找不到剩余空位的了(或者他能坐下的前提必然是另一个人站起来)。
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; int n,m,ans,_empty=0,_empty1=0,top=1,cnt1=0; struct node{int l,r; friend bool operator <(node a,node b){ return b.r<a.r;} }p[200010],p1[200010],c; bool cmp(node a,node b){return a.l<b.l;} bool cmp1(node a,node b){return a.r<b.r;} priority_queue<node>q; int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d%d",&p[i].l,&p[i].r); sort(p+1,p+n+1,cmp); for(;p[top].l==0&&top<=n;top++) p1[++cnt1]=p[top]; for (int i=1;i<=m;i++) { _empty++; for(;p[top].l==i;top++) { if (_empty) _empty--,q.push(p[top]),ans++; else { c=q.top();if (p[top].r>c.r) q.pop(),q.push(p[top]),p1[++cnt1]=c; else p1[++cnt1]=p[top]; } } } sort(p1+1,p1+cnt1+1,cmp1); top=1; if (cnt1) { for (int i=m-_empty+1;i<=m;i++) { if (p1[top].r<=i&&top<=cnt1)ans++,top++; } } printf("%d ",n-ans); }