这道题告诉我想法正确是多么重要,先是我自己想的时候没考虑到最后的页码作为循环的终止,我一直以区间个数来终止循环,这是多么愚蠢啊!然后,我看了别人的代码,但是很不幸超时了!
我自己wa的代码,我感觉很正确就是对不了!
#include<stdio.h> #include<string.h> #include<stdlib.h> int cmp(const void *a,const void *b) { return (*(int *)a-*(int *)b); } int main(void) { int t,n,i,j,count,k,temp; int s[5002][2]; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&s[i][0],&s[i][1]); qsort(s,n,sizeof(s[0]),cmp); count=0; for(i=0,k=1;i<n&&k<n;) { if(s[i][1]>=s[k][1])/*盖住后面的 */ { k++; count++; } else if(s[i][0]==s[k][0]&&s[i][1]<=s[k][1])/*被后面盖住 */ { /*如果i被k盖住,说明中间的全部被覆盖了*/ i=k;/*k后移一位,i移到k位置*/ k++; count++; } else { i=k;/*k后移一位,i移到k位置*/ k++; } } printf("%d ",n-count); } return 0; }
然后我就看网上的算法,然后改了,不过居然超时了
#include<stdio.h> #include<string.h> #include<stdlib.h> int cmp(const void *a,const void *b) { return (*(int *)a-*(int *)b); } int s[5001][2]; int main(void) { int t,n,i,j,count,k,temp,end,sta,sum,ma; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<n;i++) scanf("%d%d",&s[i][0],&s[i][1]); qsort(s,n,sizeof(s[0]),cmp); ma=0; end = s[0][1],sta = s[0][0];/*得到比较的开始,和结束地址 */ sum = 1;/*区间个数从1开始 */ i = 1; while(i<n && s[i][0] == sta)/*找到以1为开始区间群中最大那一页页码 */ { if(end < s[i][1]) { end = s[i][1]; ma=i; } ; i++; } while(end!=n)/*当找到的页码等于最后的页码就可以停止循环 */ { j=s[ma][1];/*得到当前以i为开始区间群中最大的页码 */ sta = end+1;/*查找的页码从上一个区间群中的最后一个开始 */ i++;/*获取当前区间群的第一个 */ while(i<n && s[i][0] <= sta)/*找打这个区间群中最大的 j*/ { if(s[i][1] > j) { j = s[i][1]; ma=i; } i++; } if(j > end)/*如果区间群中最大的大于上一个区间群的最大,那么就需要增加一个了 */ { sum++; end = j; } } printf("%d ",sum); } return 0; }
最后实在没办法了,只能再找了,终于看到了一个最ok的了,就是在已经排好的区间中找多少个尾部递增序列,很轻松的解决了这题,我靠怎么都没想过这种方法!想法正确真的很重要
#include<stdio.h> #include<string.h> #include<stdlib.h> int cmp(const void *a,const void *b) { return (*(int *)a-*(int *)b); } int s[5001][2]; int main(void) { int t,n,i,j,end,sta,sum,p,max; scanf("%d",&t); while(t--) { scanf("%d",&end);/*最后的页码号*/ for(i=0;i<end;++i) { scanf("%d %d",&s[i][0],&s[i][1]); } qsort(s,end,sizeof(s[0]),cmp); n=0 ; p=0 ; sum=1 ; while(sum<=end) { max=-1 ;/*每一次求新递增序列的最大值,这个值就需要初始化*/ for(i=p;i<end;++i)/*循环页码区间,找到连续递增最大的页码*/ { if(s[i][0]<=sum) { if((s[i][1]>=sum)&&(s[i][1]>max))/*更新最大的页码*/ { max=s[i][1] ; } } else /*如果页码递减就跳出*/ break ; } sum=max+1 ;/*在后面递增区间中找出比前一个递增最大值,大1的页码*/ p=i ;/*跳到最大区间后面*/ ++n ;/*每一次找新递增序列的最大,就代表前面序列区间内查最大的就可以了,所以加1*/ } printf("%d ",n); } return 0; }