1. 程式人生 > >ACdream 1216 (ASC訓練1) Beautiful People(DP)

ACdream 1216 (ASC訓練1) Beautiful People(DP)

rac popu 後來 math cst mat put ring stream

題目地址: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)