NYOJ 214 最长上升子序列nlogn
普通的思路是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的更多相关文章
- HDU 1025 Constructing Roads In JGShining's Kingdom(求最长上升子序列nlogn算法)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1025 解题报告:先把输入按照r从小到大的顺序排个序,然后就转化成了求p的最长上升子序列问题了,当然按p ...
- 【算法】最长公共子序列(nlogn)
转载注明出处:http://blog.csdn.net/wdq347/article/details/9001005 (修正了一些错误,并自己重写了代码) 最长公共子序列(LCS)最常见的算法是时间复 ...
- [poj 1533]最长上升子序列nlogn树状数组
题目链接:http://poj.org/problem?id=2533 其实这个题的数据范围n^2都可以过,只是为了练习一下nlogn的写法. 最长上升子序列的nlogn写法有两种,一种是变形的dp, ...
- HDU5748---(记录每个元素的 最长上升子序列 nlogn)
分析: 给一个序列,求出每个位置结尾的最长上升子序列 O(n^2) 超时 #include "cstdio" #include "algorithm" #def ...
- 最长公共子序列 nlogn
先来个板子 #include<bits/stdc++.h> using namespace std; , M = 1e6+, mod = 1e9+, inf = 1e9+; typedef ...
- nyoj 36 最长公共子序列【LCS模板】
最长公共子序列 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...
- nyoj 36 最长公共子序列
描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列. tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subseque ...
- DP练习 最长上升子序列nlogn解法
openjudge 百练 2757:最长上升子序列 总时间限制: 2000ms 内存限制: 65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候, ...
- NYOJ 36 最长公共子序列 (还是dp)
这个好多算法书上都有,不仅限于<算法导论> 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描写叙述 咱们就不拐弯抹角了,如题.须要你做的就是写一个程序,得出最长公 ...
随机推荐
- 【USACO 2.4.3】牛的旅行
[描述] 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通.这样,Farmer John就有多个 ...
- ueditor 1.4.3.2 独立/单独 上传图片框原理
其实简单的说就是编辑框很多按钮,所有按钮的功能都是以command形式提供,所以execCommand就是执行这些功能的命令.有些按钮是能弹出显示一个对话框,他的基类就是dialog,而所有被弹出的d ...
- Rabbitmq init terminating in do boot 问题
其实出现这个问题的原因很简单,就是rabbitmq的安装目录中是不能带空格的,但是官方安装包会默认的将我们的程序安装到Program Files下,哭晕啊有没有.所以,我们将rabbitmq从D:\P ...
- Js监控回车事件
标题通俗的说,也就是绑定当用户按下回车键要执行的事件. 下面,入正题. 第一步,先编写简单的页面代码,这里我们只需要一个按钮就足够了.当然,还有按钮事件. <html> <head& ...
- python中read、readline和readlines的区别
read 读取整个文件 readline 读取下一行 readlines 读取整个文件到一个迭代器以供我们遍历(读取到一个list中,以供使用,比较方便). 123.txt内容 ...
- ImportError: No module named matlab
这个matlab已经改名为pylab了,你可以运行: from pylab import *
- 开启和关闭wifi的代码段
1.需要申请的权限android.permission.ACCESS_WIFI_STATE android.permission.CHANGE_WIFI_STATE android.permissio ...
- BZOJ 1013 [JSOI2008]球形空间产生器sphere
1013: [JSOI2008]球形空间产生器sphere Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3074 Solved: 1614[Subm ...
- 【转】 Linux内核中读写文件数据的方法--不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8193954 Linux内核中读写文件数据的方法 有时候需要在Linuxkernel--大 ...
- Java---练习(面试题) :字符串截取(2-最终版)
在java中,字符串"abcd"与字符串"ab你好"的长度是一样,都是四个字符. 但对应的字节数不同,一个汉字占两个字节. 定义一个方法,按照指定的字节数来取子 ...