bzoj3173 [Tjoi2013]最长上升子序列 dp Treap
2016-05-03 17:52
288 查看
bzoj3173 [Tjoi2013]最长上升子序列
题意:依此插入1-n 求每插完一次的LIS
分析:每个数是按照升序插入的,因此每新加入一个数,不会影响之前的答案,那么我们就可以求出最后的序列,这样我们可以求出以每个数为结尾的LIS,那么答案 ans[i]=max(ans[i],ans[i-1]).
LIS现学的囧……理解是挺好理解的……实现囧……
d[len]:长度为len的LIS的结尾的最小值
d[i]=max(j)+1 其中d[j] < a[i]
d单调 二分O(nlogn)
插入得到最后序列 Treap
记:
iteratorlower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值>key的第一个元素。
题意:依此插入1-n 求每插完一次的LIS
分析:每个数是按照升序插入的,因此每新加入一个数,不会影响之前的答案,那么我们就可以求出最后的序列,这样我们可以求出以每个数为结尾的LIS,那么答案 ans[i]=max(ans[i],ans[i-1]).
LIS现学的囧……理解是挺好理解的……实现囧……
d[len]:长度为len的LIS的结尾的最小值
d[i]=max(j)+1 其中d[j] < a[i]
d单调 二分O(nlogn)
插入得到最后序列 Treap
记:
iteratorlower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。
iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值>key的第一个元素。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define N 100005 #define mp make_pair #define pa pair<int,int> #define inf 1<<30 using namespace std; struct Node{int ls,rs,v,key,sz;}t ; void upd(int k){t[k].sz=t[t[k].ls].sz+t[t[k].rs].sz+1;} int num,root,n,x,cnt,a ,d ,ans ,da ; int merge(int a,int b){ if(a==0||b==0) return a+b; if(t[a].key<t[b].key){t[a].rs=merge(t[a].rs,b);upd(a);return a;} else {t[b].ls=merge(a,t[b].ls);upd(b);return b;} } pa split(int k,int x){ if(x==0) return mp(0,k); int ls=t[k].ls,rs=t[k].rs;pa tmp; if(t[ls].sz==x) {t[k].ls=0;upd(k);return mp(ls,k);} if(t[ls].sz==x-1) {t[k].rs=0;upd(k);return mp(k,rs);} if(t[ls].sz>x) {tmp=split(ls,x);t[k].ls=tmp.second;upd(k);return mp(tmp.first,k);} if(t[ls].sz<x-1) {tmp=split(rs,x-t[ls].sz-1);t[k].rs=tmp.first;upd(k);return mp(k,tmp.second);} } void ins(int x,int v){ int k=x-1; t[++num].ls=0;t[num].rs=0;t[num].sz=1; t[num].v=v;t[num].key=rand(); pa tmp=split(root,k); root=merge(tmp.first,num); root=merge(root,tmp.second); } void dfs(int i){ if(!i) return; dfs(t[i].ls); a[++cnt]=i; dfs(t[i].rs); } void getans(){ memset(d,127,sizeof(d)); d[0]=-inf;d[1]=a[1];ans[a[1]]=1; int len=1; for(int i=2;i<=n;i++){ int pos=upper_bound(d,d+len,a[i])-d; if(a[i]>d[len]) d[++len]=a[i],ans[a[i]]=len; else d[pos]=min(d[pos],a[i]),ans[a[i]]=pos; } for(int i=1;i<=n;i++) ans[i]=max(ans[i],ans[i-1]); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); } int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&x),ins(x+1,i); dfs(root); getans(); }
相关文章推荐
- 编译php-5.5.15出错,xml2-config not found
- 高并发下的 Nginx 优化
- Oracle case when用法介绍
- 打字练习
- 2016年5月3日15:55:23笔记
- Android布局 屏幕滚动方法 ScrollView
- Activity的ConfigChanges属性
- python numpy 快速处理数据
- Unity3d实现物体围绕某一点进行旋转
- Spring与Quartz的整合实现定时任务调度
- LintCode_508_Wiggle Sort
- 2017考研视屏资料计算机考研
- CFBundleName系列参数的含义
- 并查集
- 前后端分离项目
- C和C++函数互相调用
- 前台结构梳理
- excel读取 工具类
- C语言的非法与合法
- 打jar包 资源文件找不到的问题