线段树解LIS
先是nlogn的LIS解法
/*
LIS nlogn解法
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
//结尾的数字越小,说明相同长度下当前序列越优
int lis[],a[];//lis[i]表示长度为i的最优的结尾数
int n,len=;
int find(int x){//找到lis中第一个大于等于x的数的下标
int l=,r=len;
while(l<r){
int mid=l+r>>;
if(lis[mid]>=x)
r=mid;
else l=mid+;
}
return l;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
lis[]=a[];len++;
for(int i=;i<=n;i++){//按顺序处理每一个数
if(a[i]>lis[len])//可以更新新长度了
lis[++len]=a[i];
else{//对于一个a[i],可以更新以它为结尾的最长lis的结尾
int pos=find(a[i]);//找到lis中第一个大于等于a[i]的数,pos也是以那个数结尾的长度
lis[pos]=a[i]; //把那个数替换了
}
}
printf("%d\n",len);
return ;
}
线段树解LIS
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 10005
int len[maxn<<];
int dp[maxn];
int a[maxn];
void build(int l,int r,int rt){
if(l==r){
len[rt]=;
return;
}
int m=l+r>>;
build(lson);
build(rson);
}
void pushup(int rt){
len[rt]=max(len[rt<<],len[rt<<|]);
}
void update(int pos,int val,int l,int r,int rt){
if(l==r){
len[rt]=val;
return;
}
int m=l+r>>;
if(pos<=m) update(pos,val,lson);
else update(pos,val,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && R>=r){
return len[rt];
}
int m=l+r>>;
if(R<=m) return query(L,R,lson);
else if(L>=m) return query(L,R,rson);
return max(query(L,m,lson),query(m+,R,rson));
}
int main(){
int n;
while(scanf("%d",&n)==){
int temp=-;
memset(dp,,sizeof dp);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
temp=max(temp,a[i]);
}
build(,temp,);
int ans=;
//找到以小于a[i]的值为结尾的lis,值+1保存在dp[i]中,下一步再把这个dp值更新到线段树中
for(int i=;i<=n;i++){
if(i!=) update(a[i-],dp[i-],,temp,);
if(a[i]>=)
dp[i]=query(,a[i]-,,temp,)+;
else dp[i]=;//a[i]是0的情况
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return ;
}
hdu4521 求间隔为d的lis
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100010
int a[maxn],dp[maxn],n,d;//用dp存储以第i个数为结尾的lis
int tree[maxn<<];//保存以【l,r】结尾的lis
inline void pushup(int rt){
tree[rt]=max(tree[rt<<],tree[rt<<|]);
}
void build(int l,int r,int rt){
if(l==r){
tree[rt]=;
return;
}
int m=l+r>>;
build(lson);
build(rson);
pushup(rt);
}
//把val更新到pos位置,以pos值结尾的lis为val
void update(int pos,int val,int l,int r,int rt){
if(l==r){
tree[rt]=val;
return;
}
int m=l+r>>;
if(pos<=m)
update(pos,val,lson);
else
update(pos,val,rson);
pushup(rt);
}
//查询值在【L,R】之间的最大lis
int query(int L,int R,int l,int r,int rt){
if(L<=l && R>=r){
return tree[rt];
}
int m=l+r>>,ret=-;
if(R<=m) return query(L,R,lson);
else if(L>m) return query(L,R,rson);
else return max(query(L,m,lson),query(m+,R,rson));
// return ret;
}
int main(){
int temp,ans;
while(scanf("%d%d",&n,&d)==){
ans=temp=-;
memset(dp,,sizeof dp);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
temp=max(temp,a[i]);//找到最大的值
}
build(,temp,);//线段树的区间是0-temp,必须从0开始
for(int i=;i<=n;i++){
if(i-d->=)//必须相隔d+1及以上,把这个点更新进去
update(a[i-d-],dp[i-d-],,temp,);
if(a[i]>=)//找到之前更新以数值小于a[i]为结尾的最长lis
dp[i]=query(,a[i]-,,temp,)+;
else dp[i]=;
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
}
线段树解LIS的更多相关文章
- cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈
/* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...
- Codeforces.264E.Roadside Trees(线段树 DP LIS)
题目链接 \(Description\) \(Solution\) 还是看代码好理解吧. 为了方便,我们将x坐标左右反转,再将所有高度取反,这样依然是维护从左到右的LIS,但是每次是在右边删除元素. ...
- 线段树解Insertion Sort Advanced Analysis
题目出处 题意描述: 这个题目提问的是,在插入排序的序列给定的情况下,求最少需要移动的次数. 序列的长度n <=10^5 序列中的元素a[i] <=10^6 一组数据中case数t < ...
- 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码
- POJ - 3264 Balanced Lineup 线段树解RMQ
这个题目是一个典型的RMQ问题,给定一个整数序列,1~N,然后进行Q次询问,每次给定两个整数A,B,(1<=A<=B<=N),求给定的范围内,最大和最小值之差. 解法一:这个是最初的 ...
- 1521. War Games 2(线段树解约瑟夫)
1521 根据区间和 来确定第k个数在哪 #include <iostream> #include<cstdio> #include<cstring> #inclu ...
- poj2299--B - Ultra-QuickSort(线段树,离散化)
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 41215 Accepted: 14915 ...
- hdu 1394 Minimum Inversion Number(这道题改日我要用线段树再做一次哟~)
Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...
- cf842D 01字典树|线段树 模板见hdu4825
一般异或问题都可以转换成字典树的问题,,我一开始的想法有点小问题,改一下就好了 下面的代码是逆向建树的,数据量大就不行 /*3 01字典树 根据异或性质,a1!=a2 ==> a1^x1^..^ ...
随机推荐
- HDU1199 动态线段树 // 离散化
附动态线段树AC代码 http://acm.hdu.edu.cn/showproblem.php?pid=1199 因为昨天做了一道动态线段树的缘故,今天遇到了这题没有限制范围的题就自然而然想到了动态 ...
- 面向对象【day07】:类的属性(五)
本节内容 概述 公有属性 一.概述 前面我们讲了类的私有属性,现在我们来说说类的公有属性,这边很容易被人弄混淆,有人觉的,在__init__()构造方法中,除了私有属性,其他的都是公有属性了,其实这是 ...
- webpack配置说明
webpack是一个现代JavaScript应用程序的静态模块打包器. 它有几个核心概念: 一.entry(入口) 指示webpack应该使用哪个模块,来作为构建其内部依赖图的开始, 可以在webpa ...
- Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1) C.Producing Snow
题目链接 题意 每天有体积为Vi的一堆雪,所有存在的雪每天都会融化Ti体积,求出每天具体融化的雪的体积数. 分析 对于第i天的雪堆,不妨假设其从一开始就存在,那么它的初始体积就为V[i]+T[1. ...
- 04-接口隔离原则(ISP)
1. 背景 类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类B和类D来说不是最小接口,则类B和类D不得不去实现它们不需要的方法. 2. 定义 一个类对另一个类的依赖应该建立在最小的接口 ...
- HTML5 元素拖拽实现 及 jquery.event.drag插件
如上图片: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" c ...
- Java SE之 Eclipse错误: 找不到或无法加载主类或项目无法编译10种解决大法!【摘抄】
声明一下:此BUG确实经常困扰我许久,今日遇到很强大的一套解决办法,又怕原博主的网页以后查找不到,故此摘抄copy一份,望得各方侵权一事而谅解. 传送门先行送上:http://blog.csdn.ne ...
- saltstack系列~第一篇
一 简介:从今天开始学习saltstack 二 salt的认证系列操作 1 原理 saltstack通过/etc/salt/pki/目录下面的配置文件的密钥进行通信,master端接受minion端后 ...
- mysql 查询优化~join算法
一简介:参考了几位师兄,尤其是M哥大神的博客,让我恍然大悟,赶紧记录下二 原理: mysql的三种算法 1 Simple Nested-Loop Join 将驱动表/外部表的结果集作为循环基础数据,然 ...
- python - logging模块应用
logging日志模块应用: import logging # logging.basicConfig( # #定义日志级别,共5个级别,默认级别为warning级别,所以debug和info级别不添 ...