先是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的更多相关文章

  1. cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈

    /* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...

  2. Codeforces.264E.Roadside Trees(线段树 DP LIS)

    题目链接 \(Description\) \(Solution\) 还是看代码好理解吧. 为了方便,我们将x坐标左右反转,再将所有高度取反,这样依然是维护从左到右的LIS,但是每次是在右边删除元素. ...

  3. 线段树解Insertion Sort Advanced Analysis

    题目出处 题意描述: 这个题目提问的是,在插入排序的序列给定的情况下,求最少需要移动的次数. 序列的长度n <=10^5 序列中的元素a[i] <=10^6 一组数据中case数t < ...

  4. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)

    传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码

  5. POJ - 3264 Balanced Lineup 线段树解RMQ

    这个题目是一个典型的RMQ问题,给定一个整数序列,1~N,然后进行Q次询问,每次给定两个整数A,B,(1<=A<=B<=N),求给定的范围内,最大和最小值之差. 解法一:这个是最初的 ...

  6. 1521. War Games 2(线段树解约瑟夫)

    1521 根据区间和 来确定第k个数在哪 #include <iostream> #include<cstdio> #include<cstring> #inclu ...

  7. poj2299--B - Ultra-QuickSort(线段树,离散化)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 41215   Accepted: 14915 ...

  8. hdu 1394 Minimum Inversion Number(这道题改日我要用线段树再做一次哟~)

    Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...

  9. cf842D 01字典树|线段树 模板见hdu4825

    一般异或问题都可以转换成字典树的问题,,我一开始的想法有点小问题,改一下就好了 下面的代码是逆向建树的,数据量大就不行 /*3 01字典树 根据异或性质,a1!=a2 ==> a1^x1^..^ ...

随机推荐

  1. ElasticSearch 批量增加索引

    服务端批量增加索引,版本是5.1.1 TransportClient client; Settings esSettings = Settings.builder() .put("clust ...

  2. JAVA记录-java代码优化策略

    java代码优化策略 1.生成对象时,合理分配空间和大小:new ArrayList(100); 2.优化for循环: Vector vect = new Vector(1000); For(int ...

  3. Study 3 —— 表格

    表格基本格式: <table> <tr> <td></td> <td></td> </tr> <tr> ...

  4. Spring面向切面编程AOP(around)实战

    spring aop的环绕通知around功能强大,我们这里就不细说,直接上代码,看着注释就能明白 需要的可以点击下载源码 1.如果使用注解的方式则需要先创建个注解类 package com.mb.a ...

  5. VS2015(Xamarin)开发安卓WebApp笔记

    有关WebApp的开发,大多数人都用了第三方框架,如Cordova等.我这里没有用到这类框架,而是新建了一个WebView嵌入Assets(本地资源)来完成这个App,由于第一个练习App希望对初学者 ...

  6. MongoDB 时差问题问题

    在读取的时候,需要再次转换回来,比较麻烦. 其实,Mongo本身就已经提供了相应的处理方法,即在实体类中加个属性即可.具体如下: [BsonDateTimeOptions(Kind = DateTim ...

  7. 在安卓上用Termux安装sqlmap

    1.打开Termux执行以下命令 apt update apt install git apt install python2 // 安装sqlmap运行环境 2.从github上下载sqlmap , ...

  8. u-boot移植(四)---修改前工作:代码流程分析3---代码重定位

    一.重定位 1.以前版本的重定位 2.新版本 我们的程序不只涉及一个变量和函数,我们若想访问程序里面的地址,则必须使用SDRAM处的新地址,即我们的程序里面的变量和函数必须修改地址.我们要修改地址,则 ...

  9. cmd 命令 添加端口

    cmd 添加端口:netsh firewall add portopening tcp 45625 "telnet"

  10. JavaScript之原型|typeof|instanceof

    //var 变量X --> 对象 --> 构造器 --> 原型对象 function Person(){}; var stu = new Person(); //var stu = ...