hdu 5748(求解最长上升子序列的两种O(nlogn)姿势)
- 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=5748
树状数组:
- /*
- 对于普通的LIS:
- for(i):1~n LIS[i]=1;
- if j<i and a[j]<a[i]
- LIS[i]=LIS[j]+1
- 因此可知LIS转移需要两个条件
- 1.(j<i) 序号必须在i之前
- 2.(a[i]>a[j]) 值必须比a[i]小
- 利用树状数组的顺序操作:{查找的都是已经出现的,序号在前(满足条件1)}
- 对于每一个值,查找它在数组中的排名,再去寻找小于它的排名的最大的LIS(满足条件2)
- 这里利用到了排名,因为这样可以最大限度地压缩C数组的空间
- */
- #include <bits/stdc++.h>
- using namespace std;
- const int Max=1e5+;
- int A[Max],V[Max],L[Max],C[Max],len;
- int lowbit(int x) {return x&(-x);}
- int Sum(int x) //求值小于等于x的LIS的最大值
- {
- int ret=;
- while(x>)
- {
- if(C[x]>ret) ret=C[x];
- x-=lowbit(x);
- }
- return ret;
- }
- void Add(int x,int d) //值大于等于x的LIS都改为LIS(x)
- {
- while(x<=len)
- {
- if(d>C[x]) C[x]=d;
- x+=lowbit(x);
- }
- }
- int main()
- {
- int T;
- for(scanf("%d",&T);T;T--)
- {
- int n;
- scanf("%d",&n);
- for(int i=;i<=n;i++)
- {
- scanf("%d",&A[i]);
- V[i]=A[i];
- }
- sort(V+,V++n);
- len=unique(V+,V++n)-(V+);
- memset(C,,sizeof(C));
- int ans=,tmp,xu;
- for(int i=;i<=n;i++)
- {
- xu=lower_bound(V+,V++len,A[i])-(V);
- tmp=Sum(xu-)+;
- L[i]=tmp;
- Add(xu,tmp);
- }
- for(int i=;i<=n;i++)
- {
- if(i!=) printf(" ");
- printf("%d",L[i]);
- }
- puts("");
- }
- return ;
- }
dp+二分
- /*
- 以dp[x]代表长度为x的LIS,且dp[x]==LIS长度为x的末尾值
- 每次都往前取dp[x]中最小的一个,当然在保证x尽可能地大的情况下
- 因为dp[x]是递增的,所以可以二分,l=1,r=当前最长的LIS
- 求得当前以小于当前a[i]的最长LIS
- */
- #include <bits/stdc++.h>
- using namespace std;
- const int Max=1e5+;
- int A[Max];
- int dp[Max];
- int LIS[Max];
- void Get_lis(int n)
- {
- int i,j,l,r,mid,ans;
- dp[]=A[];
- int len=;
- for(i=;i<=n;i++)
- {
- if(dp[len]<A[i]) j=++len;
- else
- {
- l=;r=len;
- ans=;
- while(l<=r)
- {
- mid=(l+r)>>;
- if(A[i]>dp[mid]&&A[i]<=dp[mid+])
- {
- ans=mid;break;
- }
- else if(A[i]>dp[mid]) l=mid+;
- else r=mid-;
- }
- j=ans+;
- }
- dp[j]=A[i];
- LIS[i]=j;
- }
- }
- int main()
- {
- int T;
- for(scanf("%d",&T);T;T--)
- {
- int n;
- scanf("%d",&n);
- for(int i=;i<=n;i++)
- {
- scanf("%d",&A[i]);
- dp[i]=;
- }
- LIS[]=;
- Get_lis(n);
- for(int i=;i<=n;i++)
- {
- if(i!=) printf(" ");
- printf("%d",LIS[i]);
- }
- puts("");
- }
- return ;
- }
其实还有一种单调队列求最长上升子序列的方法,可是不能用来解这道题
- /*
- 无解。。。
- 单调队列只能求出总体的LIS长度
- */
- #include <bits/stdc++.h>
- using namespace std;
- const int Max=1e5+;
- int que[Max];
- int main()
- {
- int T;
- for(scanf("%d",&T);T;T--)
- {
- int n,x,top=;
- scanf("%d",&n);
- for(int i=;i<n;i++)
- {
- scanf("%d",&x);
- if(x>que[top]||top==)
- {
- que[++top]=x;
- }
- else
- {
- int l=,r=top,mid,ans;
- ans=;
- while(l<=r)
- {
- mid=l+(r-l)/;
- if(que[mid]<x) l=mid+;
- else r=mid-,ans=mid;
- }
- que[ans]=x;
- }
- }
- cout<<top<<endl;
- }
- return ;
- }
hdu 5748(求解最长上升子序列的两种O(nlogn)姿势)的更多相关文章
- 求解最长递增子序列(LIS) | 动态规划(DP)+ 二分法
1.题目描述 给定数组arr,返回arr的最长递增子序列. 2.举例 arr={2,1,5,3,6,4,8,9,7},返回的最长递增子序列为{1,3,4,8,9}. 3.解答 ...
- HDU 4681 String 最长公共子序列
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4681 题意: 给你a,b,c三个串,构造一个d串使得d是a,b的子序列,并且c是d的连续子串.求d最大 ...
- hdu 1025 dp 最长上升子序列
//Accepted 4372 KB 140 ms //dp 最长上升子序列 nlogn #include <cstdio> #include <cstring> #inclu ...
- hdu 5489(LIS最长上升子序列)
题意:一个含有n个元素的数组,删去k个连续数后,最长上升子序列 /*思路参考GoZy 思路: 4 2 3 [5 7 8] 9 11 ,括号表示要删掉的数, 所以 最长上升子序列 = ...
- hdu 5532(最长上升子序列)
Input The first line contains an integer T indicating the total number of test cases. Each test case ...
- Python动态规划求解最长递增子序列(LIS)
原始代码错误,移步博客查看O(N^2)及优化的O(N*logN)的实现:每天一道编程题--最长递增子序列
- 算法练习--- DP 求解最长上升子序列(LIS)
问题描写叙述: 对于2,5,3,1,9,4,6,8,7,找出最长上升子序列的个数 最长上升子序列定义: 对于i<j i,j∈a[0...n] 满足a[i]<a[j] 1. 找出DP公式:d ...
- HDU 1159.Common Subsequence-最长公共子序列(LCS)
Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- 最长上升子序列算法(n^2 及 nlogn) (LIS) POJ2533Longest Ordered Subsequence
问题描述: 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列 ...
随机推荐
- tp框架 中的时间 查询范围
$where['add_time'] = array(array('egt',$starttime),array('elt',$endtime),'AND');
- Python自动化 【第六篇】:Python基础-面向对象
目录: 面向过程VS面向对象 面向对象编程介绍 为什么要用面向对象进行开发 面向对象的特性:封装.继承.多态 面向过程 VS 面向对象 面向过程编程(Procedural Programming) ...
- 34、Shiro框架入门三,角色管理
//首先这里是java代码,就是根据shiro-role.ini配置文件中的信息来得到role与用户信息的对应关系//从而来管理rolepublic class TestShiroRoleTest e ...
- 进阶篇:以IL为剑,直指async/await
接上篇:30分钟?不需要,轻松读懂IL,这篇主要从IL入手来理解async/await的工作原理. 先简单介绍下async/await,这是.net 4.5引入的语法糖,配合Task使用可以非常优雅的 ...
- Linux_09------Linux上系统扫描和安全策略
先谢慕课网/** * linux系统扫描技术 * * 主机扫描.路由扫描.批量服务扫描.系统安全策略(防SYN和ddos攻击) */ /** * 主机扫描 * ping fping hping * * ...
- UART IP和UVM的验证平台
UART是工程师在开发调试时最常用的工具的,其通信协议简单.opencores 网站提供了兼容16550a的UART IP其基本特性如下: uart16550 is a 16550 compatibl ...
- Add Binary <leetcode>
Given two binary strings, return their sum (also a binary string). For example,a = "11"b = ...
- VS2008中调试dll
1.运行dll实例时,会直接弹出一个小框: 选择可拉起这个dll的exe运行就可以调试了 2.以后每次都会直接运行了,要重新选择程序,弹出上面的框,需要在project-->debugging- ...
- proc文件系统在内核中的表现
当Linux内核启动起来之后,我们可以通过proc虚拟文件系统来查看内的中的一些动态信息. 例如:可以 cat /proc/misc 来查看系统中装载的所有misc类设备 cat /proc/d ...
- Linux(centos)系统各个目录的作用详解
Linux(centos)系统各个目录的作用详解 文件系统的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码 ...