线段树解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^..^ ...
随机推荐
- sql server复制数据到excel格式变成字符串
sql server复制数据到excel格式变成字符串,结果数据都保存在第一个格子里面. 我点击连同标题一起复制,然后粘贴到excel,结果是这样子的.... 这不是我想要的结果,在网上查询了好多,结 ...
- 用Java实现几种常见的排序算法
用Java语言实现的各种排序,包括插入排序.冒泡排序.选择排序.Shell排序.快速排序.归并排序.堆排序.SortUtil等. 插入排序: package org.rut.util.algorith ...
- impala记录-安装kudu和impala
1.配置/etc/yum.repos.d clouder-kudu.repo [cloudera-kudu]# Packages for Cloudera's Distribution for kud ...
- python-web开发环境搭建
一.安装distribute或setuptools,我用的distribute 下载链接:https://pypi.python.org/pypi/distribute [root@yeebian o ...
- zabbix微信预警出现的问题
系统环境:centos7.3 zabbix_server: 3.0.3 3.0.6 问题描述 zabbix预警突然不能发送微信,需要修复 排查步骤 1. 检查微信企业平台应用的key是否过期,结果没过 ...
- dubbo序列化
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序列化:把字节序列恢复为对象的过程称为对象的反序列化. dubbo 支持多种序列化方式并且序列化是和协议相对应的.比如:dubbo协议的 dub ...
- AtCoder Regular Contest 077 E - guruguru
https://arc077.contest.atcoder.jp/tasks/arc077_c 有m个点围成一个圈,按顺时针编号为1到m,一开始可以固定一个位置x,每次操作可以往顺时针方向走一步或直 ...
- 枚举专项练习_Uva725(Division)_Uva11059(Maximun Product)
//Uva725 #include <iostream> #include <cstring> #include <cstdlib> #include <cs ...
- DotNetBar 中Ribbon汉化
private void frmMain_Load(object sender, System.EventArgs e) { // Ribbon汉化代码 ...
- QMessageBox消息框
QMessageBox提供两套接口来实现,一种是static functions(静态方法调用),另外一种 the property-base API(基于属性的API) #需要 from PyQt5 ...