1.问题描述
强大的kAc建立了强大的帝国,但人民深受其学霸及23文化的压迫,于是勇敢的鹏决心反抗。
kAc帝国防守森严,鹏带领着小伙伴们躲在城外的草堆叶子中,称为叶子鹏。
kAc帝国的派出的n个看守员都发现了这一问题,第i个人会告诉你在第li个草堆到第ri个草堆里面有人,要求你计算所有草堆中最少的人数,以商议应对。
“你为什么这么厉害”,得到过kAc衷心赞美的你必将全力以赴。
2.输入格式
第一行一个数字n,接下来2到n+1行,每行两个数li和ri,如题。
3.输出格式
输出一个数,表示最少人数。
4.样例输入
5
2 4
1 3
5 7
1 8
8 8
5.样例输出
3
6.数据规模和约定
30%的数据n<=10
70%的数据n<=100
100%的数据n<=1000
所有数字均在int表示范围内
7.思路
有n个看守员,每个人只能发现第li个草堆到第ri个草堆中有人,需要找到所有草堆中最少有多少人。
定义:二维数组a[i][2],a[i][0]表示左端点,a[i][1]表示右端点。
t为当前区间i的右端点。
A数组为标记数组,若区间i满足条件,则加入到A数组中。
思路:首先将每个小区间按右端点值从小到大排序,然后比较当前区间i的右端点与下一个区间i+1左端点的大小情况,若下一个区间i+1左端点值大,则标记下一个区间i+1的A数组对应位置元素为1,并更新t为下一区间i+1的右端点值。重复此操作,直到n个区间全部找完。
最后根据A数组的情况,若值为1,则sum++,最后输出sum的值,则为最少人数。
以样例输入为例,画出示意图。
按区间右端点从小到大排序,若无重合,就将A数组对应位置标记为1,最后找出A数组中元素为1的个数。
8.实现:C++代码
#include<iostream>
using namespace std;
int main(){
int n;
cin>>n;
int a[1001][2]={0};
for(int i=0;i<n;i++){
cin>>a[i][0]>>a[i][1];
}
//需要找到能覆盖所有草堆的 最小数
//将每个区间按右端点排序
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++) {
if(a[i][1]>a[j][1]){
int t1=a[i][0];
a[i][0]=a[j][0];
a[j][0]=t1;
int t2=a[i][1];
a[i][1]=a[j][1];
a[j][1]=t2;
}
}
}
//将最小的右端点和下一个区间的左端点比较,若下一个区间的左端点大于当前最小的右端点,说明两区间未重合,标记下一个区间,并且更新最小右端点为该区间的右端点。
int A[100]={0};//标记数组
int t=a[0][1];//最小右端点
A[0]=1;
for(int j=1;j<n;j++){
if(a[j][0]>t){//左端点大于于右端点
A[j]=1;
t=a[j][1];
}
}
int sum=0;
for(int i=0;i<n;i++){
if(A[i]==1)sum+=1;
//cout<<A[i]<<" ";
}
cout<<sum;
return 0;
}