树状数组优化LIS到nlogn,网上找了好多,感觉讲得都不是很明白,正好自己复习整理一下。

基本的DP方程 f[i]=max(f[i],f[j]+1) (j<i且a[j]<a[i])

定义一个数组b

以a[i]为下标

存储 以a[i]结尾的最长上升子序列长度

例如 序列 5 2 1 3 4

最终b数组如下

i 1 2 3 4 5
b 1 1 2 3 1

定义它有什么好处呢?

每次转移f[i],是找f[j]的过程,有两个条件:

1. f[j]最大值

2. j<i

第二个j<i好说,用循环卡范围在[1,i-1]即可。

那第一个条件呢?a在[1,i-1]的最大值,区间最值,RMQ问题?

用什么呢?ST表?不行,我们要更改。

注意到这个区间一定是一个前缀区间,那树状数组呢? 树状数组本质是求前缀和的,当然可以改造成求前缀最大值啦。

void query(int now){
int ret=0;
while(now){
ret=max(ret,t[now]);
now-=now&-now;
}
return ret;
} void updata(int now,int w){
while(now<=n){
t[now]=max(t[now],w);
now+=now&-now;
}
}

再具体考虑一下转移,先考虑限制a[j]<a[j]的问题

把a数组离散化,1-n个下标对应1-n个数

定义v为a[i]

那就是求出b[1],b[2],… ,b[v-1]的最大值,这个可以用树状数组。

那j<i的问题呢?

换言之,b[1~v-1]是可以求最大值,那怎么*保证这些比a[i]小的数一定在i前面*呢?

答案是:不需要保证

在i前面的数,之前已经更新过,所以b数组中这些数有了值,而i之后的数,尚未访问过,就是0。

0是不影响最大值的。

所以,我们的大体思路已经成型了:

  1. 求出b[1],b[2],…,b[v-1]的最大值

  2. 用这个最大值+1更新b[v]

再次强调上述的v是里当前正在更新的那个数,也就是a[i],i是下标,v是树状数组的下标。

所以,这个b数组不需要真实存在,用树状数组假装它存在,实际上维护前缀最大值就行。

复杂度估计一下,循环遍历n个数,每次找前缀最大值logn,合计O(nlogn)

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<algorithm>
using namespace std; const int MAXN=20000; int a[MAXN],tmp[MAXN],f[MAXN];
int n; int t[MAXN];
inline void updata(int now,int w){
while(now<=n){
t[now]=max(t[now],w);
now+=now&-now;
}
}
inline int query(int now){
int ret=0;
while(now){
ret=max(ret,t[now]);
now-=now&-now;
}
return ret;
} int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
tmp[i]=a[i];
}
sort(tmp+1,tmp+1+n);
int tot=unique(tmp+1,tmp+1+n)-tmp;
for(int i=1;i<=n;i++)
a[i]=lower_bound(tmp+1,tmp+1+tot,a[i])-tmp;
int ans=1;
for(int i=1;i<=n;i++){
f[i]=query(a[i]-1)+1;
updata(a[i],f[i]);
ans=max(f[i],ans);
}
cout<<ans<<endl;
return 0;
}

[模板] LIS的更多相关文章

  1. [模板]LIS(最长上升子序列)

    转载自:最长上升子序列(LIS)长度的O(nlogn)算法 最长上升子序列nlogn算法 在川大oj上遇到一道题无法用n^2过于是,各种纠结,最后习得nlogn的算法 最长递增子序列,Longest ...

  2. 【小小复习·大米饼】

    (一)数位DP模板 ·LIS的数位DP: ·含b进制数个数+数形结合的数位DP ·平衡数的数位DP: (二)网络流问题 ·Edmonds_Karp:(见书)·Dinic(见书)·ISAP(见书)·例题 ...

  3. 学大伟业 Day 4 培训总结

    今天讲的全是dp... 不多废话,先看一道经典的模板LIS(最长不下降子序列) 一.LIS 给定一个长度为N的数列,求最长上升子序列 例:1 7 2 8 3 4 答案:1 2 3 4 代码: #inc ...

  4. nlogn LIS模板

    nlogn 模板 最长上升 #include<bits/stdc++.h> using namespace std; ; int n,x,y,a[N],num[N],d[N],len; / ...

  5. 动态规划模板1|LIS最长上升子序列

    LIS最长上升子序列 dp[i]保存的是当前到下标为止的最长上升子序列的长度. 模板代码: int dp[MAX_N], a[MAX_N], n; int ans = 0; // 保存最大值 for ...

  6. LIS严格递增和非递减模板

    2017-09-10 16:51:03 writer:pprp 严格递增的LIS模板 #include<stdio.h> #include<string.h> #include ...

  7. LCS/LIS/LCIS 模板总结

    /************************* LCS/LIS/LCIs模板总结: *************************/ /*************************** ...

  8. LIS n^2&nlogn模板

    LIS nlogn模板 http://acm.hdu.edu.cn/showproblem.php?pid=1950 #include <iostream> #include <st ...

  9. 最长上升子序列(LIS)nlogn模板

    参考https://www.cnblogs.com/yuelian/p/8745807.html 注意最长上升子序列用lower_bound,最长不下降子序列用upper_bound 比如123458 ...

随机推荐

  1. bzoj 3261 最大异或和【可持久化trie】

    因为在后面加数字又求后缀和太麻烦,所以xor[p...n]=xor[1...n]^xor[p-1...n]. 首先处理出来区间异或前缀和,对前缀和建trie树(在最前面放一棵0表示最开始的前缀和 然后 ...

  2. Tensorflow多线程输入数据处理框架(一)——队列与多线程

    参考书 <TensorFlow:实战Google深度学习框架>(第2版) 对于队列,修改队列状态的操作主要有Enqueue.EnqueueMany和Dequeue.以下程序展示了如何使用这 ...

  3. class JsonItemExporter(BaseItemExporter):

    class JsonItemExporter(BaseItemExporter):这个类的实现和几年前的实现有了点小变化,主要就是是否添加换行

  4. Qt样式表之一:Qt样式表和盒子模型介绍

    一.Qt样式表介绍 Qt样式表是一个可以自定义部件外观的十分强大的机制,可以用来美化部件.Qt样式表的概念.术语和语法都受到了HTML的层叠样式表(Cascading Style Sheets, CS ...

  5. 喵哈哈村的魔法考试 Round #1 (Div.2) ABCD

    官方题解: http://www.cnblogs.com/qscqesze/p/6418555.html#3623453 喵哈哈村的魔法石 描述 传说喵哈哈村有三种神奇的魔法石:第一种魔法石叫做人铁石 ...

  6. idea web项目热部署

    之前用idea写web项目的时候,一直都是改一点东西就要重启一下,很烦.今天终于忍受不了百度了一下idea怎么热部署web项目. 在此记录下. 第一步 编辑tomcat配置 第二步 选择打包的项目,并 ...

  7. hash系列集合的性能优化

    hash系列的集合: HashSet.LinkedHashSet     采用hash算法决定元素在集合中的存储位置 HashMap.LinkedHashMap.Hashtable   采用hash算 ...

  8. 关于Android发送短信获取送达报告的问题

    最近公司开发一个项目,要求app能够发送短信并获取送达报告.这本不是一个什么难题,实现这一功能的代码一搜一大把,那么这么简单的一个问题,为什么我要在这里提出来呢?那是因为我在写代码的时候掉入了一个坑, ...

  9. Android如何用阿里云的API进行身份证识别

    准备工作:在libs下添加 alicloud-Android-apigateway-sdk-1.0.1.jar,commons-codec-1.10-1.jar 在build.gradle添加  co ...

  10. Centos 6 安装python2.7.6

    centos 是自带python的.但是版本稍微旧一些.搞python开发,肯定要用新一点的稳定版.所以,要升级一下python. 先去python主站下载python的源码包:Python-2.7. ...