题目描述 Description:
给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。
输入描述 Input Description
输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。
输出描述 Output Description
输出第一行是一个整数表示最多剩下的线段数。
样例输入 Sample Input
3
6 3
1 3
2 5
样例输出 Sample Output
2
思路
**这题数据坑人,左右端点不是按顺序给的,有可能左端点比右端点还大,输入的时候要判断交换一下。
还有就是好久不写快排了,中间出了几次错。
说一下本题思路,思想就是贪心,没什么算法,要求保留尽量多的线段,那就是说在同一段区间里,当然是线段越短越好,于是我们按照线段的左端点排序,然后先将第一条线段作为起始,然后向后遍历,这时我们遍历到的线段的左端点一定在上一条确定线段的左端点的右边,于是可以不管左端点,只看右端点,若是该线段的右端点在上一条确定线段的左边,则一定可以用当前线段替换上一条确定的线段且这时得到的解不会比之前的解更差,这样就确定了我们选线段的原则。至于线段的计数,那么就是说我们当前遍历的线段的左端点大于上一条确定线段的右端点,这时我们已经没有必要去替换上一条线断了,则将此线段加入已确定序列,即ans++
代码
中间注释部分是调试快拍用的。。。。**
#include<iostream>
#include<cstdio>
using namespace std;
int a[101],b[101];
void swap(int *x,int *y) {
int t=*x;*x=*y;*y=t;
}
void QCsort(int l,int r) {
if(l>=r) return;
if(r-l==1) {
if(a[l]>a[r]) {
swap(a[l],a[r]);
swap(b[l],b[r]);
}
return;
}
int mid=(l+r)/2,left=l,right=r;
while(left!=right) {
while(left<mid&&a[left]<=a[mid]) left++;
while(right>mid&&a[right]>=a[mid]) right--;
swap(a[left],a[right]);swap(b[left],b[right]);
if(left==mid) mid=right;
else if(right==mid) mid=left;
}
//
// printf("left=%d right=%d mid=%d a[mid]=%d\n",l,r,mid,a[mid]);
// for(int i=1;i<=40;i++) {
// printf("%d %d\n",a[i],b[i]);
// }
//
QCsort(l,mid);QCsort(mid+1,r);
}
int main() {
freopen("in.txt","r",stdin);
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d%d",&a[i],&b[i]);
if(a[i]>b[i]) swap(a[i],b[i]);
}
QCsort(1,n);int now=b[1],ans=1;
for(int i=1;i<=n;i++) {
//
// printf("%d %d\n",a[i],b[i]);
//
if(a[i]>=now) { now=b[i];ans++; }
if(b[i]<now) now=b[i];
}
printf("%d",ans);
return 0;
}