[arc076F]Exhausted?

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",n-ans);
    
}

 

posted @ 2018-08-17 16:15  _雨后阳光  阅读(249)  评论(0编辑  收藏  举报