HDU 5773 The All-purpose Zero(O(nlgn)求LIS)
http://acm.hdu.edu.cn/showproblem.php?pid=5773
题意:
求LIS,其中的0可以看做任何数。
思路:
因为0可以看做任何数,所以我们可以先不管0,先求一遍LIS,最后再加上0的个数就可以了。当然,每个数需要减去它前面0的个数。
还有这题如果用dp求LIS是要超时的,从别人那里学习了更快的求LIS的方法。
假设存在一个序列d[..] = ,可以看出来它的LIS长度为5。n
下面一步一步试着找出它。
我们定义一个序列B,然后令 i = to 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了
首先,把d[]有序地放到B里,令B[] = ,就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2。这时Len=
然后,把d[]有序地放到B里,令B[] = ,就是说长度为1的LIS的最小末尾是1,d[]=2已经没用了,很容易理解吧。这时Len=
接着,d[] = ,d[]>B[],所以令B[+]=B[]=d[]=,就是说长度为2的LIS的最小末尾是5,很容易理解吧。这时候B[..] = , ,Len=
再来,d[] = ,它正好加在1,5之间,放在1的位置显然不合适,因为1小于3,长度为1的LIS最小末尾应该是1,这样很容易推知,长度为2的LIS最小末尾是3,于是可以把5淘汰掉,这时候B[..] = , ,Len =
继续,d[] = ,它在3后面,因为B[] = , 而6在3后面,于是很容易可以推知B[] = , 这时B[..] = , , ,还是很容易理解吧? Len = 了噢。
第6个, d[] = ,你看它在3和6之间,于是我们就可以把6替换掉,得到B[] = 。B[..] = , , , Len继续等于3
第7个, d[] = ,它很大,比4大,嗯。于是B[] = 。Len变成4了
第8个, d[] = ,得到B[] = ,嗯。Len继续增大,到5了。
最后一个, d[] = ,它在B[] = 4和B[] = 8之间,所以我们知道,最新的B[] =,B[..] = , , , , ,Len = 。
于是我们知道了LIS的长度为5。
!!!!! 注意。这个1,,,,9不是LIS,它只是存储的对应长度LIS的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。虽然最后一个d[] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 和 ,那么就可以把8更新到d[], 9更新到d[],得出LIS的长度为6。
然后应该发现一件事情了:在B中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN)~~~~~于是算法的时间复杂度就降低到了O(NlogN)~! 转自:http://blog.csdn.net/shuangde800/article/details/7474903
原理
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
using namespace std; const int maxn=+; int a[maxn];
int d[maxn];
int n; int Search(int x,int left,int right)
{
while(left<=right)
{
int mid=left+(right-left+)/;
if(x<d[mid]) right=mid-;
else left=mid+;
}
return left;
} int dp(int n)
{
int len=;
d[]=a[];
for(int i=;i<n;i++)
{
if(a[i]>d[len])
{
len=len+;
d[len]=a[i];
}
else
{
int pos=Search(a[i],,len);
d[pos]=a[i];
}
}
return len;
} int main()
{
//freopen("D:\\input.txt","r",stdin);
int T;
scanf("%d",&T);
for(int kase=;kase<=T;kase++)
{
scanf("%d",&n);
int num=;
int cnt=;
for(int i=;i<n;i++)
{
int x;
scanf("%d",&x);
if(x==) num++;
else a[cnt++]=x-num;
}
if(num==n) {printf("Case #%d: %d\n",kase,num);continue;}
int ans=dp(cnt);
printf("Case #%d: %d\n",kase,ans+num);
}
return ;
}
HDU 5773 The All-purpose Zero(O(nlgn)求LIS)的更多相关文章
- hdu 5773 The All-purpose Zero 最长上升子序列+树状数组
题目链接:hdu 5773 The All-purpose Zero 官方题解:0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的. 因此我们可以把0拿出来,对剩下的做O(nl ...
- HDU 5773:The All-purpose Zero(贪心+LIS)
http://acm.hdu.edu.cn/showproblem.php?pid=5773 The All-purpose Zero Problem Description ?? gets an ...
- hdu 2865 Polya计数+(矩阵 or 找规律 求C)
Birthday Toy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意: 给一个序列由 ...
- HDU 5773 The All-purpose Zero (变形LIS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5773 0可以改变成任何数,问你严格递增的子序列最长是多少. 猜测0一定在最长上升子序列中用到,比如2 ...
- 【动态规划】【二分】【最长上升子序列】HDU 5773 The All-purpose Zero
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 题目大意: T组数据,n个数(n<=100000),求最长上升子序列长度(0可以替代任何 ...
- HDU 5773 The All-purpose Zero(树状数组)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5773 [题目大意] 给出一个非负整数序列,其中的0可以替换成任意整数,问替换后的最长严格上升序列长 ...
- hdu 5773 The All-purpose Zero 线段树 dp
The All-purpose Zero 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5773 Description ?? gets an seq ...
- HDU 5773 最长上升子序列
题意 给出一个序列 问它的最长严格上升子序列多长 这个序列中的0可以被替代为任何数 n的范围给出了1e5 所以平常的O(n*n)lis不能用了 在kuangbin的模板里有O(nlogn)的模板 套上 ...
随机推荐
- JavaWeb-HttpServletResponse对象一
web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象,和代表响应的response对象.resquest和response对象既然代表请求和响应,那么要 ...
- centos删除乱码名称的文件
常规方法rm已经木有办法删除该文件了. 原理: 当文件名为乱码的时候,无法通过键盘输入文件名,所以在终端下就不能直接利用rm,mv等命令管理文件了.但是每个文件都有一个i节点号,可以通过i节点号来管理 ...
- MyBatis3用户指南
1. 范围和生命周期 SqlSessionFactoryBuilder -->SqlSessionFactory-->SqlSession-->Mapper 实例 SqlSe ...
- Jmeter(八)Jmeter监控tomcat
1.配置tomcat的配置文件conf/tomcat-users.xml 2. 在“线程组”上右键“添加”--“配置元件”--“HTTP授权管理器”,这里主要是让JMeter能够通过Tomcat的基本 ...
- Oracle获取当前session ID的方法
1.使用v$mystat视图获取当前session的ID select sid from v$mystat; 2.使用userenv内部函数获取当前session的ID select userenv( ...
- @FindBy、@FindBys、@FindAll的区别
原文地址http://blog.csdn.net/tea_wu/article/details/21080789 selenium-webdriver中获取页面元素的方式有很多,使用注解获取页面元素是 ...
- Linux系统——文件系统与LVM 逻辑
格式化命令 mkfs. mkswap mkfs格式化数据磁盘 # mkfs -t ext4 /dev/sdb1 # mkfs.ext4 /dev/sdb1 -t 指定格式化文件类型 -b 指定bloc ...
- 如何获知PHP程序占用多少内存(复制)
想要知道编写的 PHP 脚本需要占用多少内存么?很简单,直接使用 PHP 查看当前分配给 PHP 脚本的内存的函数 memory_get_usage() 就可以了 下面是使用示例: 复制代码 代码如下 ...
- 基于TSUNG对MQTT进行压力测试-测试结果
一.TSUNG压测前概念温习 https://www.cnblogs.com/lingyejun/p/7898873.html 二.TSUNG在服务器上的安装步骤 Tsung压测时总连接数 = 本机可 ...
- Word 为标题设置段前段后间距设置与异常
一.概述 在进行Word文档写作时,常常要求我们对(节)标题设置段前段后间距.例如: (2)按照标题的不同,分别采用不同的段前段后间距: 标题级别 段前段后间距 章标题 30磅 一级节标题 18磅 二 ...