线段树解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^..^ ...
随机推荐
- H5新特性之video audio
1.标签 <video src="~~~" autoplay loop controls controlslist="nodownload nofullscreen ...
- 数据结构(六)查找---多路查找树(B树)
B 树 B树与B+树 一:定义 B树(B-树)是一种平衡的多路查找树.-3树和2--4树都是B树的特例.节点最大的孩子数组称为B树的阶(order),因此,-3树是3阶B树,--4树是4阶B树. 二: ...
- UVALive 4725 Airport(二分)
题目链接 题意 机场有两种飞机,每小时一些飞机到达,每小时安排一架飞机起航.求任意时刻中两种飞机数目的最大值的最小值. 分析 首先肯定是二分来做.这里的难点在于如何判断飞机数目是否合法.一开始忽略了某 ...
- 流媒体技术学习笔记之(十七)FFmpeg 3.3《希尔伯特》-新版本的亮点
FFmpeg 3.3“Hilbert”,一个新的主要版本的一些亮点: 苹果Pixlet解码器 NewTek SpeedHQ解码器 QDMC音频解码器 PSD(Photoshop Document)解码 ...
- VMware WorkStation9.0 安装centos-6.4
1,设置虚拟机内存为8G时,启动报内存不足错误: Not enough physical memory is available to power on this virtual machine 解决 ...
- VS设置以管理员方式运行
一直以为VS不能直接以管理员方式运行,原来它是在高级里的.
- C# unicode 转中文
//Unicode 转中文 private void button1_Click(object sender, EventArgs e) { string unicode = @"\U5fa ...
- 安卓中location.href或者location.reload 不起作用
链接:https://www.cnblogs.com/joshua317/p/6163471.html 在移动wap中,经常会使用window.location.href去跳转页面,这个方法在绝大多数 ...
- luogu P3576 [POI2014]MRO-Ant colony
传送门 一群蚂蚁能被吃,也就是走到指定边的两端点之一要走到另一端点时有\(k\)只,我们可以从这两端点逆推,记两个值为走到某个点时最后会被吃掉\(k\)只蚂蚁的蚂蚁数量范围,式子下面有,很好理解(雾) ...
- servlet相关
servlet是在服务器端运行的一个小程序.一个servlet就是一个java类,并且可以通过“请求-响应”编程模型来访问的这个驻留在服务器内存里的servlet程序. 1.生命周期 2.内置对象 r ...