[ 题解 ] [ 暴力 ] CodeForces 976/C C.Nested Segments
训练赛http://codeforces.com/group/NVaJtLaLjS/contest/236426/problem/B
即http://codeforces.com/problemset/problem/976/C
题意:输入n个区间 (1 ≤ n ≤ 3·105),输出任意两个嵌套区间的编号。不存在输出-1 -1。
输出没有唯一答案,而且子区间在前。满足A ≤ a < b ≤ B 则 (a,b) 是 (A,B) 子区间。
参考下图,第2行的区间是3、4、5、6行的子区间,而不是11行的子区间。这里可以输出2 3/2 4/2 5/2 6中的任意一个。
示例:
Input:
5 1 10 2 9 3 9 2 3 2 9
Output:
2 1
该示例有多个答案,比如
3 1或4 1;
3 2或4 2;
2 5或5 2。
Input:
3 1 5 2 6 6 20
Output:
-1 -1
这题不是无脑暴力,这数据量太大了,逐一比较会导致超时。所以要找出其中规律。
嵌套区间的判断条件已经知道了:A ≤ a < b ≤ B,那么非嵌套的呢?
看图,a < A且b < B,则 (a,b) (A,B) 区间不嵌套。
你想到了什么?
把示例2的图画出来,你会发现每个区间的左右端点都比前一个大。
只有这种情况下不存在嵌套区间。我想到这里你已经知道要怎么做了。
把输入的区间进行排序,按左端点或者右端点从小到大排序。
假设不存在嵌套区间,那么从1到N遍历,代表区间左右端点的变量F,B必定严格递增。
如果不是,说明有区间是嵌套的,停下判断两个区间的大小,按顺序输出两个编号即可结束;
否则在遍历完成后输出-1 -1表明没有嵌套区间的存在。
需要一个结构体来存区间端点及其编号,再对结构体排序,以保证排序不会打乱这些信息。
对结构体排序,当然要把大小判断告诉sort/qsort函数。
丑代码如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 struct Segment 6 { 7 int left,right; 8 int num; 9 }sgmt[300003]={{0}}; 10 int N=0; 11 12 int compare(const void *p1,const void *p2) 13 { 14 struct Segment *a=p1,*b=p2; 15 return a->left - b->left ; 16 } 17 18 int Answer(int A,int B) 19 { 20 int lenA=sgmt[A].right-sgmt[A].left; 21 int lenB=sgmt[B].right-sgmt[B].left; 22 if(lenA<lenB) 23 { 24 printf("%d %d\n",sgmt[A].num,sgmt[B].num); 25 } 26 else 27 { 28 printf("%d %d\n",sgmt[B].num,sgmt[A].num); 29 } 30 } 31 32 int main() 33 { 34 scanf("%d",&N); 35 for(int n=0;n<N;n++) 36 { 37 scanf("%d%d",&sgmt[n].left,&sgmt[n].right); 38 sgmt[n].num=n+1; 39 } 40 qsort(sgmt,N,sizeof(struct Segment),compare); 41 42 int front=sgmt[0].left,back=sgmt[0].right; 43 for(int n=1;n<N;n++) 44 { 45 if( sgmt[n].left > front && sgmt[n].right > back ) 46 { 47 front=sgmt[n].left,back=sgmt[n].right; 48 } 49 else 50 { 51 Answer(n-1,n); 52 return 0; 53 } 54 } 55 puts("-1 -1"); 56 return 0; 57 }