列表

详情


NC23036. 华华听月月唱歌

描述

月月唱歌超级好听的说!华华听说月月在某个网站发布了自己唱的歌曲,于是把完整的歌曲下载到了U盘里。然而华华不小心把U盘摔了一下,里面的文件摔碎了。月月的歌曲可以看成由1到N的正整数依次排列构成的序列,它现在变成了若干个区间,这些区间可能互相重叠。华华想把它修复为完整的歌曲,也就是找到若干个片段,使他们的并集包含1到N(注意,本题中我们只关注整数,见样例1)。但是华华很懒,所以他想选择最少的区间。请你算出华华最少选择多少个区间。因为华华的U盘受损严重,所以有可能做不到,如果做不到请输出-1。

输入描述

第一行两个正整数N、M,表示歌曲的原长和片段的个数。
接下来M行,每行两个正整数L、R表示第i的片段对应的区间是[L,R]。

输出描述

如果可以做到,输出最少需要的片段的数量,否则输出-1。

示例1

输入:

4 2
1 2
3 4

输出:

2

示例2

输入:

4 2
1 1
3 4

输出:

-1

示例3

输入:

10 5
1 1
2 5
3 6
4 9
8 10

输出:

4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 104ms, 内存消耗: 1144K, 提交时间: 2019-03-10 14:30:08

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
pair<int,int>pn[N];
 int n,m,le,k,num;
int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++)
	cin>>pn[i].first>>pn[i].second;
	sort(pn,pn+m);
	le=1;k=0;num=0;
	while(le<=n){
		int res=0;
		while(pn[k].first<=le&&k<=m)
			res=max(res,pn[k].second),k++;
		if(res>=le)
			le=res+1,num++;
		else{
			num=-1;
			break;
		}
	}
	cout<<num<<endl;
	return 0;
}

Python3 解法, 执行用时: 713ms, 内存消耗: 32484K, 提交时间: 2023-05-15 16:11:34

n, m = map(int, input().split())
arr = []
for _ in range(m):
    arr.append(list(map(int, input().split())))
    
arr.sort(key=lambda x:(x[0], x[1]))
res = 0
tmp = 0
i = 0
while i<m and tmp<n:
    if arr[i][0] > tmp +1:
        break
    endmax = tmp
    while i<m and arr[i][0]<=tmp+1:
        endmax = max(endmax, arr[i][1])
        i += 1
    res += 1
    tmp = endmax
if tmp<n:
    print(-1)
else:
    print(res)

C++(clang++ 11.0.1) 解法, 执行用时: 32ms, 内存消耗: 1196K, 提交时间: 2023-07-30 16:01:54

#include<iostream>
using namespace std;
int main(){
	int n,m,i,j,x=1,x1,y=0;
	int l[100010],r[100010];
	scanf("%d %d",&n,&m);
	for(i=1;i<=m;i++)
		scanf("%d %d",&l[i],&r[i]);
	while(1){
		x1=0;
		if(x>n) break;
		y++;
		for(i=1;i<=m;i++)
			if(x>=l[i]&&x<=r[i]&&r[i]>=x1) x1=r[i]+1;
		x=x1;
		if(x1==0) {
			printf("-1");
			return 0;
		}
	}
	printf("%d",y);
	return 0;
}

上一题