码迷,mamicode.com
首页 > 其他好文 > 详细

ACdream 1216 (ASC训练1) Beautiful People(DP)

时间:2017-07-27 15:44:00      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:return   iostream   nod   type   node   ack   blank   线段树   size   

题目地址:http://acdream.info/problem?

pid=1216

这题一開始用的是线段树。后来发现查询的时候还须要DP处理。挺麻烦。。也就不了了之了。。后来想到,这题事实上就是一个二维的最长上升子序列。

要先排序,先按左边的数为第一keyword进行升序排序。再按右边的数为第二keyword进行降序排序。这种话,第一keyword同样的的肯定不在一个同一个上升子序列中。然后仅仅对第二keyword进行复杂度为O(n*logn)的DP,找出最长上升序列,然后处理前驱,并输出就可以。

代码例如以下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL long long
struct node
{
    int x, y, num;
}fei[110000];
int cmp(node x, node y)
{
    if(x.x==y.x)
        return x.y>y.y;
    return x.x<y.x;
}
int a[110000], d[110000], pre[110000], len, b[110000];
int bin_seach(int x)
{
    int low=0, high=len, mid, ans;
    while(low<=high)
    {
        mid=low+high>>1;
        if(a[mid]>=x)
        {
            high=mid-1;
            ans=mid;
        }
        else
        {
            low=mid+1;
        }
    }
    return ans;
}
int main()
{
    int n, i, j, pos, cnt;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&fei[i].x,&fei[i].y);
            fei[i].num=i+1;
        }
        sort(fei,fei+n,cmp);
        len=1;
        a[1]=fei[0].y;
        d[0]=-1;
        d[1]=0;
        memset(pre,-1,sizeof(pre));
        for(i=1;i<n;i++)
        {
            if(fei[i].y>a[len])
            {
                a[++len]=fei[i].y;
                pre[i]=d[len-1];
                d[len]=i;
            }
            else
            {
                pos=bin_seach(fei[i].y);
                a[pos]=fei[i].y;
                pre[i]=d[pos-1];
                d[pos]=i;
            }
        }
        printf("%d\n",len);
        cnt=0;
        /*for(i=0;i<n;i++)
        {
            printf("%d ",fei[i].num);
        }
        puts("");*/
        for(i=d[len];i!=-1;i=pre[i])
        {
            b[cnt++]=fei[i].num;
            //printf("%d\n",i);
        }
        for(i=0;i<cnt-1;i++)
            printf("%d ",b[i]);
        printf("%d\n",b[cnt-1]);
    }
    return 0;
}


ACdream 1216 (ASC训练1) Beautiful People(DP)

标签:return   iostream   nod   type   node   ack   blank   线段树   size   

原文地址:http://www.cnblogs.com/wzjhoutai/p/7244727.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!