博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj千题计划316:bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)
阅读量:7061 次
发布时间:2019-06-28

本文共 1533 字,大约阅读时间需要 5 分钟。

 

插入的数是以递增的顺序插入的

这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某个数结尾的最长上升子序列产生影响

所以 先原序列求出来,输出即可

 

还原原序列的方法:

可以用平衡树,dfs序就是原序列

嫌麻烦,不想写,所以  树状数组

假设最后一个数是n,插入位置是y,

倒数第二个数是n-1,插入位置是x

那么y就是n的最终位置

如果y在x后面,那么x就是n-1的最终位置

如果y在x前面,那么x+1就是n-1的最终位置

所以 如果倒序插入每个数,

若数m的插入位置为p,

数m的最终位置就是当前序列 的 第p个空位

这可以二分+树状数组确定 数m的位置 

 

注意求LIS时,求出的f[i] 时 以i结尾的LIS

要求回答 序列的LIS,所以要跟f[i-1]取大

 

#include
#include
#include
using namespace std;#define N 100001#define lowbit(x) x&-xint n;int p[N];int c[N];int a[N];int dp[N],m;int f[N];void read(int &x){ x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }} void add(int pos,int x){ while(pos<=n) { c[pos]+=x; pos+=lowbit(pos); }}int query(int x){ int sum=0; while(x) { sum+=c[x]; x-=lowbit(x); } return sum;}int find(int x){ int l=1,r=n,mid,tmp; while(l<=r) { mid=l+r>>1; if(mid-query(mid)>=x) tmp=mid,r=mid-1; else l=mid+1; } return tmp;}void init(){ read(n); for(int i=1;i<=n;++i) read(p[i]); int pos; for(int i=n;i;--i) { pos=find(p[i]+1); a[pos]=i; add(pos,1); }}void pre_LIS(){ dp[m=1]=a[1]; f[a[1]]=1; int pos; for(int i=2;i<=n;++i) { if(a[i]>dp[m]) { dp[++m]=a[i]; f[a[i]]=m; } else { pos=lower_bound(dp+1,dp+m+1,a[i])-dp; if(a[i]

 

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/8978474.html

你可能感兴趣的文章
SHELL编程练习-获得指定目录下的所有文件及文件夹的大小
查看>>
XML 命名空间(XML Namespaces)
查看>>
一个IT人的未来短期计划和阶段总结
查看>>
openstack issue 4
查看>>
一次真实的网购装机实战经历
查看>>
通过virt工具安装管理KVM虚拟机
查看>>
Hadoop测试常见问题和测试方法
查看>>
利用IPSec安全策略阻断内网违规外联(一)
查看>>
运维85条军规
查看>>
zabbix监控oracle 12c
查看>>
IT人论房价 (四) 泡沫和破灭
查看>>
DOM编程
查看>>
Linux时间同步服务
查看>>
微信为什么会成功?
查看>>
离开行业:女ITer工作十年对系统4个9可靠性的思考
查看>>
用JDTS连接MS SQLServer数据库
查看>>
아프리카 BJ 박현서,
查看>>
VDI序曲二十四 APP-V客户端安装及虚拟应用程序体验
查看>>
DB2性能调节工作总结
查看>>
Office 365技术支持
查看>>