ACderamoj 1216 Beautiful People 二路最长单调递增序列

来源:互联网 发布:陈华编程社区 编辑:程序博客网 时间:2024/06/05 05:28

题目链接:http://acdream.info/problem?pid=1216

题目大意:给你N行数,每行有两个数下x,y,问满足xi>xi-1&&yi>yi-1的序列的长度,并输出任一满足条件的行数组合。

解题思路:和最长单调递增子序列差不多,但是要输出路径,用dp[]记录最长递增子序列的长度,用pre[]记录每个位置的数的前面的一个满足要求的数的位置。

代码如下:

//dp[k]记录的是长度为k的序列的末尾位置//pre[i]记录第i个位置的前一个位置,用于输出过程#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100005struct node{    int a,b,id;}s[N];int dp[N],pre[N];bool cmp(node a,node b){    if(a.a==b.a) return a.b>b.b;    return a.a<b.a;}int bin(int l,int r,int x){    while(l<r)    {        int m=(l+r)>>1;        if(s[dp[m]].b<x) l=m+1;        else r=m;    }    return l;}int main(){    int n,k;    while(~scanf("%d",&n))    {        for(int i=1;i<=n;i++)            scanf("%d%d",&s[i].a,&s[i].b),s[i].id=i;        sort(s+1,s+n+1,cmp);        k=1;dp[1]=1;        for(int i=2;i<=n;i++)        {            if(s[i].b>s[dp[k]].b)//因为已经按照a排序,所以如果s[i].b>s[dp[k]].b,可以保证s[i].a>s[dp[k]].a            {                pre[i]=dp[k];                dp[++k]=i;            }            else            {                int pos=bin(1,k,s[i].b);                dp[pos]=i;                pre[i]=dp[pos-1];            }        }        printf("%d\n",k);        int w=dp[k--];        printf("%d",s[w].id);        while(k--)        {            w=pre[w];            printf(" %d",s[w].id);        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击