P1803. 凌乱的yyy / 线段覆盖

题目背景

快 noip 了,yyy 很紧张!

题目描述

现在各大 oj 上有 nn 个比赛,每个比赛的开始、结束的时间点是知道的。

yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。

所以,他想知道他最多能参加几个比赛。

由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 22 个及以上的比赛。

输入格式

第一行是一个整数 nn,接下来 nn 行每行是 22 个整数 ai,bi (ai<bi)ai​,bi​ (ai​<bi​),表示比赛开始、结束的时间。

输出格式

一个整数最多参加的比赛数目。

输入数据 1

3
0 2
2 4
1 3

输出数据 1

2

这道题有两种写法,但本质思路都相同

这道题没有明显算法,总体写法也不是很难,重点在于对排序应用的掌握:

话不多说,我们就来一起温习一下排序吧。

1.普通排序

 sort(数组名+0/1,数组名+长度+0/1,判断规则)

这种排序方法编写容易,思路简单,但时间复杂度高,为n*log2n,在一些测试点数据较大的题目中要谨慎使用,本题需对还是和结束同时排序,所以不能使用

2.结构体排序

在sort排序之上引申出的排序,基本与sort排序相同、

结构体排序弥补了sort不能实现的功能,在本题中可以应用,写法如下:

struct node
{
    int s,e;
};
node a[1000005];
bool cmp(node x,node y)
{
    return x.e<y.e;
}

3.归并排序

主要思想为分治思想,将要排序的主体一分为二,不断拆分排序然后融合

归并排序有很多潜在特质,所以在很多难题中都会出现隐藏的应用,比如用来求逆序对……,比较难以分析,同时也是一种稳定的排序,时间复杂度为O(nlogn),模板如下

void msort(int s,int t)
{
    if(s==t) return;
    int mid=(s+t)/2;
    msort(s,mid);
    msort(mid+1,t);
    int i=s,j=mid+1,k=s;
    while(i<=mid&&j<=t){
        if(a[i]<=a[j]){r[k]=a[i];k++;i++;}
        else{r[k]=a[j];k++;j++;ans+=mid-i+1;}
    }
    while(i<=mid){r[k]=a[i];k++;i++;}
    while(j<=t){r[k]=a[j];k++;j++;}
    for(int i=s;i<=t;i++) a[i]=r[i];
}

4.快速排序

主体思想就是不断比较,交换……

是一种不稳定的排序,好的话是O(nlogn),坏的话是O(n^2),模板如下

void qsort(int x,int y)
{
    int i,j,mid,t;
    i=x;j=y;mid=last[(x+y)/2];
    while(i<=j){
        while(last[i]<mid) i++;
        while(last[j]>mid) j--;
        if(i<=j){
            t=last[j];last[j]=last[i];last[i]=t;
            t=began[j];began[j]=began[i];began[i]=t;
            i++;
            j--;
        }
    }
    if(x<j) qsort(x,j);
    if(i<y) qsort(i,y);
}

这道题可以说是一个区间贪心,如图:

事实证明按后端点排序才能更多的完成 

 ①结构体写法:

AC code:

#include <bits/stdc++.h>
using namespace std;
struct node
{
    int s,e;
};
node a[1000005];
bool cmp(node x,node y)
{
    return x.e<y.e;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].s>>a[i].e;
    }
    sort(a+1,a+1+n,cmp);
    int b=a[1].e,ans=1;
    for(int i=2;i<=n;i++){
        if(a[i].s>=b){
            ans++;
            b=a[i].e;
        }
    }
    cout<<ans;
    return 0;
}

②快速排序写法: 

#include<bits/stdc++.h>
using namespace std;
int began[1000005],last[1000005];
void qsort(int x,int y)
{
    int i,j,mid,t;
    i=x;j=y;mid=last[(x+y)/2];
    while(i<=j){
        while(last[i]<mid) i++;
        while(last[j]>mid) j--;
        if(i<=j){
            t=last[j];last[j]=last[i];last[i]=t;
            t=began[j];began[j]=began[i];began[i]=t;
            i++;
            j--;
        }
    }
    if(x<j) qsort(x,j);
    if(i<y) qsort(i,y);
}
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>began[i]>>last[i];
    qsort(1,n);
    int ans=0;
    int t=-1;
    for(int i=1;i<=n;i++){
        if(began[i]>=t){
            ans++;
            t=last[i];
        }
    }
    cout<<ans<<endl;
    return 0;
}
  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值