题解 P1803 【凌乱的yyy】

· · 题解

看到好多大佬用贪心。。。表示萌新老老实实用的DP

进入正题:

定义f[i]表示在前[i]场比赛中最多可以参加几场比赛,

由此得出方程:f[i]=max(f[i-1],f[temp]+1);

f[temp]指从f[i-1]向前找到的第一个允许参加第i场比赛的f[]

由于每次循环时都向前找一次temp会浪费太多时间,又因为f[]是单调递增的,

故可以令temp在循环时逐步递增,这样时间复杂度就降到了O(n).

代码如下:

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
#include<ctime>
#include<cstdlib>
#include<algorithm>
using namespace std; 
struct qj{
    int l,r;
};
bool cmp(qj a,qj b){
    if(a.r!=b.r)return a.r<b.r;
    return a.l<b.l;
}
qj game[1000005];
int f[1000005];
int i,n,temp;
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        scanf("%d%d",&game[i].l,&game[i].r);  
    sort(game+1,game+1+n,cmp);
    f[0]=0;
    temp=0;
    for(i=1;i<=n;i++){
        while(game[temp+1].r<=game[i].l)temp++;
        f[i]=max(f[i-1],f[temp]+1);
    }
    printf("%d\n",f[n]);
    return 0;
}