2017国家集训队作业[arc076d/f][Exhausted?]

2017国家集训队作业[arc076d/f][Exhausted?]

题意:

​ 有\(N\)个人,\(M\)把椅子,给出\(、、、L_i、R_i\)表示第\(i\)个人可以选择编号为\(1\sim L_i\)\(R_i\sim M\)的椅子,求至少要加多少张椅子才能让每人都有椅子坐?(\(N,M\le2*10^5\)

题解:

​ 场上看到这道题,woc,这不是sb的线段树或前缀和优化网络流建边二分图匹配吗?(这沙茶= =)

​ 听dcx说,这题网络流建出来是分层图,流量是\(INF\)的可以贪心模拟?不会= =。

​ 场后听到题解,还真是贪心,而且贪心方法五花八门。。。这里讲我最后用的方法。

​ 按\(L_i\)排升序,枚举,若到第\(i\)个人时,\(L_i < i\),那就把前\(i\)个人中\(R_i\)最小的人匹配的椅子放到后半段去。优先队列维护。枚举\(R_i\)同理,注意终止边界就可以了。仔细想想,这贪心还挺对的,本蒟蒻场上满脑子优化建图还是太弱。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
inline int rd()
{
    static int x,f;
    x=0,f=1;
    char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
const int N=200010;
struct node{int l,r;bool bo;}a[N];
int n,m,l,r,ans=0;
bool cmpl(node a,node b){return (a.l==b.l)?a.r>b.r:a.l<b.l;}
bool cmpr(node a,node b){return a.r>b.r;}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("ina.txt","r",stdin);
	#endif
	n=rd();m=rd();
    l=1;r=m;
    fo(i,1,n)a[i].l=rd(),a[i].r=rd();
    sort(a+1,a+n+1,cmpl);
    fo(i,1,n){
    	if(l>m)break;
        if(l<=a[i].l){
            ans++;l++;
            a[i].bo=true;
        }
	}
    sort(a+1,a+n+1,cmpr);
    fo(i,1,n){
        if(r<l)break;
        if(!a[i].bo&&r>=a[i].r){
            ans++;r--;
            a[i].bo=true;
        }
	}
    printf("%d\n",n-ans);
    return 0;
}

UPD:2018/8/19 补上了代码

posted @ 2018-08-18 19:34  Jackyhh  阅读(327)  评论(3编辑  收藏  举报