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

代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define  inf  0x3f3f3f3f
int dp[200220],list[200220],a[200220];//dp[i]保存lis为i时最小的元素,list保存每个元素的lis;
int main()
{
    int n,i,j,k,p;
    while (cin>>n){p=0;
    memset(dp,inf,sizeof(dp));
        for(i=0;i<n;i++){
            scanf("%d",&a[i]);
    *lower_bound(dp,dp+n,a[i])=a[i];          //记录更新长度对应的最大潜力元素时,顺便记录下该元素对应的LIS长度
    list[p++]=lower_bound(dp,dp+n,a[i])-dp+1;
        }
        k=lower_bound(dp,dp+n,inf)-dp;     //总的LIS
        cout<<k<<endl;
        int m=k;
        for(i=n-1;i>=0;i--){                          //从右至左扫描一遍直至找全LIS长度
            if(k==list[i])
            dp[k--]=a[i];
            if(!k) break;
    }
    for(i=1;i<=m;i++)printf("%d\n",dp[i]);
    }
    return 0;
}
 
 
更快的解法,减小二分搜索的次数:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define  inf  0x3f3f3f3f
int dp[200220],list[200220],a[200220];
int main()
{
    int n,i,j,k,p;
    while (cin>>n){p=0;k=0;
    memset(dp,inf,sizeof(dp));
        for(i=0;i<n;i++){
            scanf("%d",&a[i]);
 if(a[i]>dp[k])  dp[++k]=a[i];      // 设置k为当前最长lis值
   else*lower_bound(dp,dp+k,a[i])=a[i];  
     list[p++]=lower_bound(dp,dp+k,a[i])-dp+1;
        }
    //    k=lower_bound(dp,dp+n,inf)-dp;
    k=k+1;
        printf("%d\n",k);
        int m=k;
        for(i=n-1;i>=0;i--){
            if(k==list[i])
            dp[k--]=a[i];
            if(!k) break;
    }
    for(i=1;i<=m;i++)printf("%d\n",dp[i]);
    }
    return 0;
}
从右至左扫描的必要性:
由于是求单调上升子序列,所以最大值定在右侧。
又具有相同lis的不同元素中,潜力最大的也在右侧。
即假设一个元素的lis为n(n>2),则在这个元素之前定有lis为(n-1)且小于此元素的原宿存在。

二分求LIS并打印结果的更多相关文章

  1. hdu5256 二分求LIS+思维

    解题的思路很巧,为了让每个数之间都留出对应的上升空间,使a[i]=a[i]-i,然后再求LIS 另外二分求LIS是比较快的 #include<bits/stdc++.h> #define ...

  2. hdu 1025LIS思路同1257 二分求LIS

    题目: Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...

  3. HDU 5773 The All-purpose Zero(O(nlgn)求LIS)

    http://acm.hdu.edu.cn/showproblem.php?pid=5773 题意: 求LIS,其中的0可以看做任何数. 思路: 因为0可以看做任何数,所以我们可以先不管0,先求一遍L ...

  4. nlogn求LIS(树状数组)

    之前一直是用二分 但是因为比较难理解,写的时候也容易忘记怎么写. 今天比赛讲评的时候讲了一种用树状数组求LIS的方法 (1)好理解,自然也好写(但代码量比二分的大) (2)扩展性强.这个解法顺带求出以 ...

  5. UVA 10635 Prince and Princess—— 求LCS(最长公共子序列)转换成 求LIS(最长递增子序列)

    题目大意:有n*n个方格,王子有一条走法,依次经过m个格子,公主有一种走法,依次经过n个格子(不会重复走),问他们删去一些步数后,重叠步数的最大值. 显然是一个LCS,我一看到就高高兴兴的打了个板子上 ...

  6. 【模板】O(nlongn)求LIS

    合理运用单调性降低复杂度 平常用的都是O(n^2)的dp求LIS(最长不下降子序列)这里介绍O(nlogn)的算法 分析 对于可能出现的x<y<i且A[y]<A[x]<A[i] ...

  7. Codeforces 486E LIS of Sequence --树状数组求LIS

    题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i] ...

  8. 九度OJ 1085 求root(N, k) -- 二分求幂及快速幂取模

    题目地址:http://ac.jobdu.com/problem.php?pid=1085 题目描述: N<k时,root(N,k) = N,否则,root(N,k) = root(N',k). ...

  9. 二分求幂/快速幂取模运算——root(N,k)

    二分求幂 int getMi(int a,int b) { ; ) { //当二进制位k位为1时,需要累乘a的2^k次方,然后用ans保存 == ) { ans *= a; } a *= a; b / ...

随机推荐

  1. linux服务器文件索引inodes满了

    inode节点中,记录了文件的类型.大小.权限.所有者.文件连接的数目.创建时间与更新时间等重要的信息,还有一个比较重要的内容就是指向数据块的指针.一般情况不需要特殊配置,如果存放文件很多,需要配置. ...

  2. Linux中Postfix反病毒和垃圾邮件工具(十)

    amavisd-new amavisd-new呼叫器是一个连接MTA和内容检测工具(诸如病毒扫描工具和SpamAssassin)的高性能接口程序,使用perl语言写成.它一般通过SMTP.ESMTP或 ...

  3. python之路----继承的抽象类和接口类

    抽象类与接口类 接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数 ...

  4. Python 自学基础(四)——time模块,random模块,sys模块,os模块,loggin模块,json模块,hashlib模块,configparser模块,pickle模块,正则

    时间模块 import time print(time.time()) # 当前时间戳 # time.sleep(1) # 时间延迟1秒 print(time.clock()) # CPU执行时间 p ...

  5. Hive-查询结果导入到 MySQL

    step1:add jar /home/chenweidong/lib/hive-contrib-2.1.1-cdh.0.0.jar;add jar /home/chenweidong/lib/mys ...

  6. 20145309李昊《网络对抗技术》实验9 web安全基础实践

    本实验在同学帮助下完成 一.实验准备 1.0 实验目标和内容 Web前端HTML.能正常安装.启停Apache.理解HTML,理解表单,理解GET与POST方法,编写一个含有表单的HTML. Web前 ...

  7. 20165310 java_blog_week4

    2165310 <Java程序设计>第4周学习总结 教材学习内容总结 继承(extends) 同一个包内:继承除了private修饰的变量与方法 不同包内:不继承private和友好,继承 ...

  8. Python3基础 file open+write 对不存在的txt进行创建与写入

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  9. luogu P2184 贪婪大陆

    乍一不咋会 ╭(╯3╰)╮ 把地雷L到R看成一条线段 要求的就是区间内有多少条线段经过 很明显是要用[1,R]内的起点个数-[1,L-1]的终点个数 然后这起点和终点个数可以用简单的差分线段树来维护一 ...

  10. Unity3D学习笔记(一):Unity简介、游戏物体、组件和生命周期函数

    Project(工程.项目):工程是把游戏开发当前所需要的资源归类管理用的. Console控制台:日志.报错.调试,右上角,消息过滤 Assets:资源,存储游戏中一切用到的资源 Library:临 ...