普通的思路是O(n2)的复杂度,这个题的数据量太大,超时,这时候就得用nlogn的复杂度的算法来做,这个算法的主要思想是只保存有效的序列,即最大递增子序列,然后最后得到数组的长度就是最大子序列。比如序列7 8 9 1 2 3 来说, 就是先把第一个数输入到数组中,然后继续输入后面的数,每输入一个数都要和最后一个数比较,因为这时最后一个数一定是有效序列中最大的,如果大于最后一个数,那么就直接将它放到数组的最后就行了,如果不大于最后一个数的话,就找到第一个比他大的数,然后替换它,样例中,先输入进去7, 然后再输入8,因为8 > 7, 所以直接将8放到数组的最后,同理,9也是,当输入到1的时候,判断它不比9大,这时候就需要找第一个比1大的数,这时候就用二分查找就行了,因为这个数组这样输入进去的话,肯定是有序的,找到第一个比他大的数是7,那么就替换7,现在数组中的元素分别是1, 8, 9,继续输入2,判断它不比数组的最后一个元素大,这时候继续二分找第一个比它大的,那么将替换8,同理3将会替换9,最后数组的元素分别是1, 2, 3,这是用贪心的策略来做的,因为只有保存最小的,后面的数组成最长序列的机会才会更大,所以要保存最小的.

再比如:1 8 2 4 5 先将1保存到数组中,然后再将8保存到数组中,继续判断2,不大于最后一个元素,所以找第一个比它大的,替换8,至于为什么是这样,因为同样是序列长度为2的,1 2这个序列当然要比1 8 可能的序列要长,因为后面有4,如果1 8 的话就不能长度再加一了,所以更新最小的

代码如下;

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
const int N = + ;
int a[N];//保存当前最大的序列
int e;//表示当前数组中有几个元素
void replace_value(int n)//二分法查找替换
{
int left = , right = e;
int mid = (left + right) >> ;
while (left < right)
{
if (left + == right)
{
if (a[right] != n)//替换右值
a[right] = n;
return; }
if (a[mid] == n)
return;
if (a[mid] > n)
right = mid;
else
left = mid;
mid = (left + right) >> ;
}
}
int main()
{
int n;
while (~scanf("%d", &n))
{
e = ;
memset(a, , sizeof(a));
a[] = -;
int t;
for (int i = ; i < n; i++)
{ scanf("%d", &t);
if (t > a[e])//如果大于当前已有的数中最大的, 就将它添加到数组中
a[++e] = t;
else
replace_value(t);
}
cout << e << endl;
}
return ;
}

下面这个代码的思想和上面的基本相同,我是看的网上的,大体思路就是先将数据输入到一个数组中,然后在一个一个的判断,找每个元素应该在的位置,也就是上面的那种思想,不过不如上面的那个简单

#include <stdio.h>

const int N =  + ;
int a[N], b[N];//a来存放输入的元素,b来存放当前最长子序列元素
//寻找n所在b当中的位置,二分查找,时间复杂度logn;
int search_pos(int n, int len)
{
int left = , right = len;
int mid = (left + right) >> ;
while (left <= right)
{
if (b[mid] == n)
return mid;
else if (b[mid] < n)
left = mid + ;
else
right = mid - ;
mid = (left + right) >> ;
}
return left;
}
int main()
{
int n;
while (~scanf("%d", &n))
{
for (int i = ; i < n; i++)
scanf("%d", &a[i]);
b[] = a[];
int len = ;
int j;
for (int i = ; i < n; i++)
{
j = search_pos(a[i], len);//找到第一个比他大的位置,如果已经是最大,那么就是b数组的最后一个位置
b[j] = a[i];
if (j > len)//如果是最后一个位置,len更新为j
len = j;
}
printf("%d\n", len);
}
return ;
}

NYOJ 214 最长上升子序列nlogn的更多相关文章

  1. HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...

  2. 【算法】最长公共子序列(nlogn)

    转载注明出处:http://blog.csdn.net/wdq347/article/details/9001005 (修正了一些错误,并自己重写了代码) 最长公共子序列(LCS)最常见的算法是时间复 ...

  3. [poj 1533]最长上升子序列nlogn树状数组

    题目链接:http://poj.org/problem?id=2533 其实这个题的数据范围n^2都可以过,只是为了练习一下nlogn的写法. 最长上升子序列的nlogn写法有两种,一种是变形的dp, ...

  4. HDU5748---(记录每个元素的 最长上升子序列 nlogn)

    分析: 给一个序列,求出每个位置结尾的最长上升子序列 O(n^2) 超时 #include "cstdio" #include "algorithm" #def ...

  5. 最长公共子序列 nlogn

    先来个板子 #include<bits/stdc++.h> using namespace std; , M = 1e6+, mod = 1e9+, inf = 1e9+; typedef ...

  6. nyoj 36 最长公共子序列【LCS模板】

    最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...

  7. nyoj 36 最长公共子序列

    描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列. tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subseque ...

  8. DP练习 最长上升子序列nlogn解法

    openjudge 百练 2757:最长上升子序列 总时间限制:  2000ms 内存限制:  65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候, ...

  9. NYOJ 36 最长公共子序列 (还是dp)

    这个好多算法书上都有,不仅限于<算法导论> 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 咱们就不拐弯抹角了,如题.须要你做的就是写一个程序,得出最长公 ...

随机推荐

  1. 用BroadcastReceiver监听网络状态的变化

    在用户浏览网络信息时,如果网络突然断开,可以及时的提醒用户网络已断开.要实现这个功能,我们可以实现一个广播接收者来接收网络状态改变的广播,当由连接状态变为断开状态时,系统会发送一条广播,广播接收者接收 ...

  2. 按钮制作技巧(css精灵效果)-高级版

    [转自己以前的文章] 无论用什么语言,大家敲程序的时候多多少少都会遇到做按钮的时候.今天分享一个之前学做按钮的技巧,有人叫做css精灵效果. 通常做按钮的思路都用附图中的第一种:两张图片交互的形式,让 ...

  3. Phaser开源2d引擎 javascript/html5游戏框架

    功能特点(Features) 易维护代码(Easy Asset Loading) Phaser可以加载图片,音频文件,数据文件,文本文件和自动解析精灵图和纹理地图集数据(出口纹理封隔器或Flash C ...

  4. Delphi Keycode

    Keycode表 字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 74 S 83 1 49 B 66 K 75 T 84 2 50 C 67 L ...

  5. iOS开发网络篇—XML数据的解析

     iOS开发网络篇—XML数据的解析 iOS开发网络篇—XML介绍 一.XML简单介绍 XML:全称是Extensible Markup Language,译作“可扩展标记语言” 跟JSON一样,也是 ...

  6. 编程规范之 if 语句的简单规则

    原文: http://www.oschina.net/translate/basic-rules-for-code-readability-and-the-if-statement 代码应该是可阅读就 ...

  7. 把图片生成Base64字符串

    public class ImgeUtils { public static String img2String(BufferedImage img,String type){ String imgS ...

  8. hdu 3912 Turn Right

    http://acm.hdu.edu.cn/showproblem.php?pid=3912 这个题我用递归深搜模拟,直接爆栈了.哭啊!为什么! 这个题最主要是能走重复格子,但是方向不一样. 我用的剪 ...

  9. 【HDOJ】1271 整数对

    枚举,假设这个数x=a*10^(i+1)+b*10^i+c,去掉b后y=a*10^i+c,x+y=n,则x+y=n(mod10^i),求出c,注意c<10^i,但2*c有可能大于10^i,因此分 ...

  10. POJ1068 Parencodings(模拟)

    题目链接. 分析: 水题. #include <iostream> #include <cstdio> #include <cstring> using names ...