题目描述:一家餐厅收到了n份订单,每份订单有开始和结束时间,餐厅可以选择接或不接,接受的订单时间必须互不重合,即任意一刻都不能被两个订单占用。问餐厅最多能接受几份订单。

啊这,乍看是经典DP,但是不能直接写,需要多思考。以订单结束顺序排序。
f[i]表示处理订单数为i时,所用的最小时间,发现f[i]有单调性。
每次对一个订单,用开始时间二分查找f[k]<lef<=f[k+1],更新f[k+1]=min(f[k+1],rig)
最后f[]数组最后不为INF的对应下标就是答案。

#include<bits/stdc++.h>
//#define ll long long
using namespace std;
unordered_map<int,int> Mp;
int n;
struct Order
{
    int lef,rig;
}a[500010];
int b[1000010];
int f[1000010],cnt=1;
bool my(Order a,Order b)
{
    if(a.rig!=b.rig)return a.rig<b.rig;
    else return a.lef<b.lef;
}
void Reunion()
{
    int k=0;
    sort(b+1,b+1+2*n);
    for(int i=1;i<=2*n;++i)
    {
        if(b[i]!=b[i-1]) Mp[b[i]]=++k;
    }
    sort(a+1,a+1+n,my);
}
int Find(int x)
{
    int lef=0,rig=cnt,mid;
    //if(lef==rig) return 1;
    while(lef+1<rig)
    {
        mid=(lef+rig)>>1;
        if(f[mid]>x) rig=mid;
        else lef=mid;
    }
    if(x>f[rig]) return rig;
    else return lef;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;++i)
    {
        cin>>a[i].lef>>a[i].rig;
        b[2*i-1]=a[i].lef,b[2*i]=a[i].rig;
    }
    Reunion();
    int x,y,z;
    f[1]=Mp[a[1].rig];
    for(int i=2;i<=n;++i)
    {
        x=Mp[a[i].lef];
        y=Mp[a[i].rig];
        //cout<<Find(x)<<endl;
        z=Find(x)+1;
        //cout<<z<<endl;
        //cout<<i<<' '<<x<<' '<<y<<endl;
        //Alt(y,z);
        if(!f[z]) f[z]=y;
        else f[z]=min(f[z],y);
        for(int j=cnt;;++j)
        {
            if(!f[j])
            {
                cnt=j-1;
                break;
            }
        }
        //for(int i=1;i<=cnt;++i)cout<<f[i]<<' ';cout<<endl; 
        //cout<<"gnerk"<<endl; 
    }
    cout<<cnt<<endl;
    //system("pause");
    return 0;
}