1275: God's ladder [DP]

30 篇文章 0 订阅
12 篇文章 1 订阅

1275: God's ladder [DP]

时间限制: 1 Sec  内存限制: 128 MB   Special Judge

题目描述

天明来到神之宫殿,在他眼前出现了若干个石柱,每个石柱上有1枚金币,天明可以任意选择一个石柱开始,然后向前方的石柱瞬移,而且他所瞬移到的石柱的高度必须要大于现在所在石柱的高度。

求天明所能获得的最大金币数以及任意一种可以获得这么多金币的路线(每个石柱的高度)。

输入

第一行一个数n,表示石柱的个数。

然后2~n+1行,每行一个石柱的高度h[i],分别是1,2,,n石柱的高度。

2<n<200100;1<= h[i] < 15000000;

输出

第一行为一个数m,表示最大金币数。

2~m+1行,每行一个数,分别是每次所瞬移到的石柱的高度。

样例输入

7
3
1
2
5
9
6
7

样例输出

5
1
2
5
6
7

思路:O(nlgn)否则超时,二分+dp;

举个例子:1   6   7   3    4     8    5

下标:       1   2   3   2    3     4    4

逆着输出:5   4    3   1(这份序列)

下标则是:4   3   2   1

#include<cstdio>
#define SIZE 200110
using namespace std;
int stack[SIZE];
int a[SIZE],f[SIZE],lis[SIZE];
int main()
{
    int i,j,n,top,temp;
    scanf("%d",&n);
    top=0;
    stack[0]=-1;
    for(i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        temp=a[i];
        if (temp>stack[top])
        {
            stack[++top]=temp;
            f[i]=top;
        }
        else
        {
            int low=1,high=top,mid;
            while(low<=high)
            {
                mid=(low+high)/2;
                if (temp>stack[mid])
                    low=mid+1;
                else
                    high=mid-1;
            }
            stack[low]=temp;
            f[i]=low;
        }
    }
    printf("%d\n",top);
    int t=top;
    for(i=n;i>=0;i--)
    {
        if(f[i]==t)
              lis[--t]=a[i];
        if(t<0)
            break;
    }
    for(i=0;i<top;i++)
        printf("%d\n",lis[i]);
    return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; 
#define SIZE 200110
int stack[SIZE];
int a[SIZE],f[SIZE],lis[SIZE];
int main()
{
    int i,j,n,temp;
    scanf("%d",&n);
    int top=0;
    stack[0]=-1;
    for(i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        temp=a[i];
        if (temp>stack[top])
        {
            stack[++top]=temp;
            f[i]=top;
        }
        else
        {
            int low=lower_bound(stack,stack+top,temp)-stack;//感觉比二分耗时    
                        stack[low]=temp;
            f[i]=low;
        }
    }
	printf("%d\n",top);
    int t=top;
    for(i=n;i>=0;i--)
    {
        if(f[i]==t)
        	lis[--t]=a[i];
        if(t<0)
            break;
    }
    for(i=0;i<top;i++)
        printf("%d\n",lis[i]);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值