Description

已知两个长度为N的数组A和B。下标从0标号至N-1。

如今定义一种D序列 (如果长度为L)。这样的序列满足下列条件:

1. 0 <= D[i] <= N-1

2. A[D[i]] < A[D[i+1]]  (0 <= i < L-1)

3. B[D[i]] > B[D[i+1]]  (0 <= i < L-1)

求满足条件的D序列的最大长度。

(事实上这样的序列叫做D序列的原因是:这道题是D题)

Input

多组数据,每组数据第一行是一个整数N。

(1 <= N <= 100000)

第二行中有N个正整数A[0]~A[N-1]。

第三行中有N个正整数B[0]~B[N-1]。

保证全部输入整数在int范围内。

Output

对每组数据。输出一个整数。表示D序列的最大长度L。

Sample Input

3
1 1 2
3 2 1
3
1 2 3
3 2 1
4
1 3 2 4
3 1 2 4

Sample Output


233

思路::将A数组,B数组以A为第一keyword,B为第二keyword进行升序排序。然后将B倒置求B的最长上升子序列。

为了避免下标排序和写比較函数。将A B 保存在pair里先排序,然后再取出来存放大到 A 中。倒置,并求最长子序列。
在求最长上升子序列时,直接用dp的方法时间复杂度为 O(n^2),会超时,所以採用其它的方法求。
方法(1)::利用lower_bound 求上升子序列O(nlogn)
 //lower_bound三个參数分别为要比較的起始点地址,终止点的地址+1(也就是左闭右开)。要比較的值(如果为d)。
//它的作用是返回一个地址。这个地址是在比較的范围内>=d的最小的值的地址。
//举个样例,a[] = {0 , 1 ,2, 4, 5, 7 } p =lower_bound(a,a+6,3),p就为 4 的地址。假设p =lower_bound(a,a+6,4),p也为 4 的地址
方法(2)::利用二分法求上升子序列O(nlogn)
利用lower_bound要在数组中进行比較,当要比較的数较大时。无法将数存放在数组中。而利用二分法能解决这一问题,但代码难度较大。
两种方法的思路是一样的。将数组A中子序列长度为 i 的最小值存放在数组S中。我们以3 2 4 6  5 7 3 为例进行演示行为遍历。列为数组S,变化的地方已经标出来。有助于理解。

在这里a[ i ] > s[ j ]&&a[i]<=s[ j + 1 ]就应该把a[ i ]放在s[
j+1 ]的位置。

所以关键就是找出 j 就知道把a[ i ]放在哪了。

上面的两种方法就是用来寻找 j的 。(在这里lower_bound直接返回 j + 1 )

我们能够发现s数组中的值必定是有序递增的。这也是能够利用二分法的一个必要条件。


演示
0 1 2 3 4
1 3      
2 2      
3 2 4    
4 2 4 6  
5 2 4 5  
6 2 4 5 7
7 2 3 5 7
         

方法(1)代码::

#include <bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int s[100005];
vector<pair<int,int> > T;//能够用vector存,也能够直接用数组 pair<int ,int> T[100005]; int main()
{
int n;
while(~scanf("%d",&n)){
T.clear();//假设不初始或要出错用数组就不须要了
for(int i = 0;i<n;i++)scanf("%d",&a[i]);
for(int i = 0;i<n;i++)scanf("%d",&b[i]);
//假设用数组应该为T[i] = {a[i],b[i]};
for(int i = 0;i<n;i++)T.push_back(make_pair(a[i],b[i]));
//sort(T,T+n);
std::sort(T.begin(),T.end());//排序
for(int i= 0;i<n;i++)a[i] = T[i].second;//把排序后的数组b取出来放到a中
reverse(a,a+n);//导致
int len = 1; s[1] = a[0];//<span style="font-family: Arial, Helvetica, sans-serif;">第一个元素首先放入 s[1]</span>
for(int i = 1;i<n;i++){//dp的思想,逐个将a中元素增加s.
int t = a[i];
if(t>s[len])s[++len] = a[i];
else{
int p = lower_bound(s+1,s+len+1,t)-s;
s[p] = t;
}
}
printf("%d\n",len);
}
return 0;
}

方法(2)代码::

#include <bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int s[100005];
vector<pair<int,int> > T; int main()
{
int n;
while(~scanf("%d",&n))
{
T.clear();
for(int i = 0;i<n;i++)scanf("%d",&a[i]);
for(int i = 0;i<n;i++)scanf("%d",&b[i]);
for(int i = 0;i<n;i++)T.push_back(make_pair(a[i],b[i]));
std::sort(T.begin(),T.end());
for(int i= 0;i<n;i++)a[i] = T[i].second;
reverse(a,a+n);
int len = 1;s[1] = a[0];
for(int i = 1;i<n;i++){
int t = a[i];
if(t>s[len]) s[++len] = a[i];
else{
int l = 1,r = len,mid;
int ans = 0;
while(l<=r)//这里的二分法採用了左闭右闭的思路
{
mid = (r+l)/2;
if(s[mid]<t){
l = mid+1;
ans=max(ans, mid);//ans即为思路中的j,j必定为s数组中小于t的最大的数
}
else r = mid-1;
}
s[ans+1] = t;
}
}
printf("%d\n",len);
}
return 0;
}

shuoj1936-D序列—最长上升子序列的更多相关文章

  1. 【模拟】CSU 1807 最长上升子序列~ (2016湖南省第十二届大学生计算机程序设计竞赛)

    题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1807 题目大意: 给你一个长度为N(N<=105)的数列,数列中的0可以被其他数 ...

  2. 最长递增子序列问题 nyoj 17单调递增最长子序列 nyoj 79拦截导弹

    一,    最长递增子序列问题的描述 设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1< ...

  3. HDU-4521 小明系列问题——小明序列 间隔限制最长上升子序列

    题意:给定一个长度为N的序列,现在要求给出一个最长的序列满足序列中的元素严格上升并且相邻两个数字的下标间隔要严格大于d. 分析: 1.线段树 由于给定的元素的取值范围为0-10^5,因此维护一棵线段树 ...

  4. 【LCS,LIS】最长公共子序列、单调递增最长子序列

    单调递增最长子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 求一个字符串的最长递增子序列的长度如:dabdbf最长递增子序列就是abdf,长度为4   输入 ...

  5. hunnu 11313 无重复元素序列的最长公共子序列转化成最长递增子序列 求法及证明

    题目:http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11313 湖师大的比赛,见我的另一篇水题题解,这里要说的 ...

  6. C语言 · 最长公共子序列 · 最长字符序列

    算法提高篇有两个此类题目: 算法提高 最长字符序列   时间限制:1.0s   内存限制:256.0MB      最长字符序列 问题描述 设x(i), y(i), z(i)表示单个字符,则X={x( ...

  7. [HAOI2007]上升序列(最长上升子序列)

    题目描述 对于一个给定的 S=\{a_1,a_2,a_3,…,a_n\}S={a1​,a2​,a3​,…,an​} ,若有 P=\{a_{x_1},a_{x_2},a_{x_3},…,a_{x_m}\ ...

  8. 【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

    nlogn求出最长上升子序列长度. 对每次询问,贪心地回答.设输入为x.当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] ...

  9. POJ - 2533 Longest Ordered Subsequence与HDU - 1257 最少拦截系统 DP+贪心(最长上升子序列及最少序列个数)(LIS)

    Longest Ordered Subsequence A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let ...

随机推荐

  1. 《一个民企CEO的职场阳谋》–读书总结(下)

    职场是一个战场,很多人几十年在这里战斗. 职场是一个熔炉,很多人大半生在这里修炼. 如果在办公室里得不到快乐,生活就不会快乐. 如果公司里头感觉不到幸福,人生就不会幸福.(以上四句来自老刘的博客) & ...

  2. 异构关系数据库(Sqlserver与Oracle)之间的数据类型转换参考

    一.Oracle到SqlServer的数据类型的转变 编号 Oracle ToSqlServer SqlServer 1 BINARY_DOUBLE VARCHAR(100) real 2 BINAR ...

  3. 使用 Xshell 连接 linux 系统

    一.下载 Xshell 链接:https://pan.baidu.com/s/1htwqpzm 密码:zau7 二.安装 Xshell 无脑下一步就可以了 三.连接 linux 四.安装 Xftp h ...

  4. jquery-layer.closeAll不执行的错觉

    在使用ajax.form提交的时候,弹出了layer插件的页面,于是我想使用layer插件提供的layer.closeAll()方法讲这个弹出的页面关闭,但是尝试了很久不行,到底是为什么呢? 过了一段 ...

  5. angular-表格

    ng-repeat 指令可以完美的显示表格. <div ng-app="myApp" ng-controller="customersCtrl"> ...

  6. MRv2 工作机制 、 公平调度器、MR压缩、边数据

    对于节点数超过 4000 的大型集群,前一节描述的 MapReduce 系统开始面临着扩展的瓶颈. 2010 年 Yahoo 的团队开始设计下一代的 MapReduce. (Yet Another R ...

  7. 不用while if 循环求 1到n的和,还用到了!!这样的运算符

    很好的题目.开始我也没有想出来. 不用while if 循环求 1到n的和 给了很多种解法,第一种是构造函数,然后累加static变量 第二种是虚函数,有父类子类,父类的结束,然后用 !!n来让 n不 ...

  8. 手写一个节点大小平衡树(SBT)模板,留着用

    看了一下午,感觉有了些了解.应该没有错,有错希望斧正,感谢 #include<stdio.h> #include<string.h> struct s { int key,le ...

  9. C++11新特性应用--介绍几个新增的便利算法(用于分区的几个算法)

    今天继续. C++11新增的关于Non-modifying sequence operations和Modifying sequence operations的算法已经写了.具体信息见之前的博客. 以 ...

  10. 关于sql中的with(nolock)

    SQL Server 中的 NOLOCK 究竟是什么意思 一般用于此类语句中:select * from t with(NOLOCK) nolock是不加锁查询.能够读取被事务锁定的数据,也称为脏读. ...