Segments

来源:互联网 发布:spss可以装在mac上吗 编辑:程序博客网 时间:2024/05/17 01:21

1078. Segments

Time limit: 1.0 second
Memory limit: 64 MB
A number of segments are lying on a line. Every segment is given with the coordinates of its endpoints. Segments are numbered from 1 to N (0 < N < 500). We assume, that one segment is inside another, if the two segments are different, the first one is fully contained in the second one, and their endpoints do not coincide. Write a program, which finds the numbers of the segments in the longest sequence of segments which are contained in. In the sequence, every segment except the last is inside the next segment in the sequence.

Input

The first line contains one integer N. Next, there are N lines, with two integers on every line, which are the coordinates of the left and the right endpoints of the corresponding segment. These coordinates are integers in the interval [–10000, 10000]. We assume that, the given segments are numbered according to their place in the input.

Output

The first line must contain one integer, equal to the number of segments in the found sequence. The following line must contain the numbers of the segments in this sequence. These numbers must be outputted, in the order in which the segments' lengths increase, starting from the smallest. If there are more than one output sequences, write any of them.

Sample

inputoutput
4-2 2-1 1-3 34 5
32 1 3
/***     设DP[i]为到第i个区间时,最大能够有多少个区间满足关系.     首先,我们需要将原来的区间按照右端点排序,如果不排,          比划一下:     n=4     区间如下:     1*************     2   ********     3  ***     4 ******     如上:dp[1]=1,dp[2]=1,dp[3]=1,dp[4]=1. = =!实际上,dp[1]=3,dp[3]=1,dp[4]=2          在为第一组找最大区间数量时,被它包含的区间没有更新,因此,没办法找到最大值.....     所以,排序后:     1  ***     2 ******     3   ********     4*************     如果,大区间能包含小区间,那小区间现在一定在大区间前面,     那我们只需要按照找最长上升子序列对每个区间的左端点进行dp.......     方程见代码:***/#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 5005struct  Segment{    int l,r;    int len;//这个没用= =!    int id;} s[maxn];int n;int dp[maxn];int pre[maxn];//pre[x]表示,x直接包含的那个区间的下标,是排序后的bool cmp(Segment a,Segment b)//按右端点排序{    return a.r<b.r;}void read(){    scanf("%d",&n);    for(int i=0; i<n; i++)    {        scanf("%d%d",&s[i].l,&s[i].r);        s[i].id=i+1;        s[i].len=s[i].r-s[i].l;    }    sort(s,s+n,cmp);//排序}int DP(){    memset(pre,-1,sizeof(pre));//初始化为-1    for(int i=0; i<n; i++)        dp[i]=1;    for(int i=0; i<n; i++)        for(int j=0; j<i; j++)            if(s[i].l<s[j].l&&s[i].r>s[j].r)//题目要求的是被包含的是与包含者左右区间端点不相同,在这点我WA了一次                if(dp[j]+1>dp[i])//求最大包含量                {                    dp[i]=dp[j]+1;                    pre[i]=j;//标记前缀                }    int max=0;    for(int i=0; i<n; i++)        if(dp[i]>dp[max])            max=i;    return max;//返还最大dp的下标}void print(int x)//用最大dp的下标寻找序列{    if(x==-1)    return ;    print(pre[x]);//这里不用考虑长度,因为,按端点排序后,一旦a区间包含b区间,b区间的长度一定小于a区间    printf("%d ",s[x].id);}int main(){    read();    int x=DP();    printf("%d\n",dp[x]);    print(x);    printf("\n");    return 0;}


原创粉丝点击