dp之最长上升子序列

普通做法是O(n^2)下面介绍:最长上升子序列O(nlogn)算法(http://blog.csdn.net/shuangde800/article/details/7474903)

/*
    HDU 1950 Bridging signals
            -----最长上升子序列nlogn算法
*/

#include<cstdio>
#include<cstring>
#define MAXN 40005

int arr[MAXN],ans[MAXN],len;

/*
    二分查找。 注意,这个二分查找是求下界的;  (什么是下界?详情见《算法入门经典》 P145)
    即返回 >= 所查找对象的第一个位置(想想为什么)

    也可以用STL的lowe_bound二分查找求的下界
*/

int binary_search(int i)
{
    int left,right,mid;
    left=0,right=len;
    while(left<right)
    {
        mid = left+(right-left)/2;
        if(ans[mid]>=arr[i]) right=mid;
        else left=mid+1;
    }
    return left;
}

int main()
{
    int t,n,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1; i<=n; ++i)
            scanf("%d",&arr[i]);

        ans[1] = arr[1];
        len=1;
        for(i=2; i<=n; ++i)
        {
            if(arr[i]>ans[len])
                ans[++len]=arr[i];
            else
            {
                int pos=binary_search(i);   // 如果用STL: pos=lower_bound(ans,ans+len,arr[i])-ans;
                ans[pos] = arr[i];
            }
        }
         printf("%d\n",len);
    }
    return 0;
}
时间: 2024-08-08 12:41:59

dp之最长上升子序列的相关文章

hdu 4352 数位dp(最长上升子序列的长度为k的个数)

http://acm.hdu.edu.cn/showproblem.php?pid=4352 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefully reading the entire description is very important. As the strongest fighting force in UESTC, xhxj grew

UVA 10100- Longest Match(dp之最长公共子序列)

题目地址:UVA 10100 题意:求两组字符串中最大的按顺序出现的相同单词数目. 思路:将字串中的连续的字母认作一个单词,依次计算出两个字符串中的单词,其中第1个字符串的单词序列为t1.word[1]-..t1.word[n],第2个字符串的单词序列为t2.word[1]-..t2.word[m].然后将每个单词当成一个字符,使用LCS算法计算出两个字符串的最长公共子序列,该序列的长度就是最长匹配. #include <stdio.h> #include <math.h> #in

hdu1257 dp(最长上升子序列)

题意:有一种拦截系统,可以打击导弹,但是打击的高度会逐渐下降,因此为了防御导弹攻击,就必须用多个系统,现给出一列导弹依次的高度,求最少需要的系统数. 这道题是最长上升子序列问题,但是我一开始其实并没有想到,最开始我的思路是依次剔除最长下降子序列,每剔除一轮就是需要一个拦截系统,然后直到全部数都剔除了就可以知道要几个拦截系统了.而且这样做就是最长下降子序列符合 dp 的思路也可以自圆其说,所以说为什么我成长得这么慢,其实就是我刷 dp 专题就使劲往怎么用 dp 上想而不是怎么做出来上想,很多时候这

dp之最长公共子序列

例1:给你两个字符串,找出最长子序列的长度. 对于字符串t, 字符串s,给定特定的i, j代表t,s的位置,只存在三种情况: 1. i == 0 ||  j==0, M[i][j] = 0; 2. t[i] == s[j], M[i][j] = min(M[j-1][j-1] + 1, M[i-1][j], M[i][j-1]);//.....不知道怎么解释.... 3. t[i] != s[j] , M[i][j] = min(M[i-1][j], M[i][j-1]);//..... 经典d

hdu1025 dp(最长上升子序列LIS)

题意:有一些穷国和一些富国分别排在两条直线上,每个穷国和一个富国之间可以建道路,但是路不能交叉,给出每个穷国和富国的联系,求最多能建多少条路 我一开始在想有点像二分图匹配orz,很快就发现,当我把穷国按顺序排了之后,富国写在它旁边,能够连接的富国就成了一个上升子序列,那么问题来了!上升子序列最长有多长? 想到了这个之后,代码就码起来吧,最开始我的做法是最土的那种,用 dp[i] 表示以 i 结尾的最长上升子序列的长度,每次对于一个 i 遍历 i 前面的所有数 j ,取小于 i 的所有 j 的最大

[NYIST16]矩形嵌套(DP,最长上升子序列)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=16 像套娃一样把矩形套起来.先给矩形从小到大排序,然后做最长上升子序列就行 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15

动态规划(DP),最长递增子序列(LIS)

题目链接:http://poj.org/problem?id=2533 解题报告: 状态转移方程: dp[i]表示以a[i]为结尾的LIS长度 状态转移方程: dp[0]=1; dp[i]=max(dp[k])+1,(k<i),(a[k]<a[i]) #include <stdio.h> #define MAX 1005 int a[MAX];///存数据 int dp[MAX];///dp[i]表示以a[i]为结尾的最长递增子序列(LIS)的长度 int main() { int

【DP】最长公共子序列

Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y="y0,y1,-,yk-1"是X的子序列,存在X的一个严格递增下标序列<i0,i1,-,ik-1>,使得对所有的j=0,1,-,k-1,有xij = yj.例如,X="ABCBDAB",Y="BCDB"是X的一个子序列. 对给

(hdu step 3.2.2)Common Subsequence(简单dp:求最长公共子序列的长度)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 976 Accepted Submission(s): 538   Probl

算法练习--- DP 求解最长上升子序列(LIS)

问题描写叙述: 对于2,5,3,1,9,4,6,8,7,找出最长上升子序列的个数 最长上升子序列定义: 对于i<j i,j∈a[0...n] 满足a[i]<a[j] 1. 找出DP公式:dp[i] = dp[j] + 1  (j<i && a[j]<a[i] && dp[i] < dp[j]+1) 2.实现代码 void Main() { DP_LIS(); Console.WriteLine(dpArr); } static int[] ar