Description

给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

Input

第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

Output

N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

Sample Input

3
0 0 2

Sample Output

1
1
2

HINT

100%的数据 n<=100000

易得,令f[i]表示以数字i结尾的最长上升子序列长度,则新加入一个数时不会影响到其他的f[i]。

在线写法:用平衡树直接模拟,每一次用位置的前缀f[i]的最大值+1来作为当前的新加入的数的f[i],然后将其插入到指定位置。输出答案时直接查找当前所有f[i]的最大值。

离线写法:求出最终序列然后nlogn求一次LIS即可,可以用树状数组或平衡树实现。

【fhq-treap 在线】

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N=1e5+;
int n,root,cnt,rt1,rt2,pos,ch[N][];
#define lc ch][0
#define rc ch][1
#define rnd ch][2
#define sz ch][3
#define v ch][4
#define mx ch][5
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
void up(int w)
{
w[sz]=w[lc][sz]+w[rc][sz]+;
w[mx]=max(w[lc][mx],w[rc][mx]);
w[mx]=max(w[mx],w[v]);
}
void split(int w,int& l,int& r,int k)
{
if(!w){l=r=;return;}
int lson=w[lc][sz];
if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
else {l=w;split(w[rc],w[rc],r,k-lson-);}
up(w);
}
int merge(int a,int b)
{
if(!a||!b)return a+b;
if(a[rnd]<b[rnd]){a[rc]=merge(a[rc],b);up(a);return a;}
else {b[lc]=merge(a,b[lc]);up(b);return b;}
}
void ins(int& w,int x,int k)
{
if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;}
int lson=w[lc][sz];
if(k<=lson)ins(w[lc],x,k);
else ins(w[rc],x,k-lson-);
up(w);
}
int query(int pos)
{
rt1=rt2=;split(root,rt1,rt2,pos);
int ans=rt1[mx];root=merge(rt1,rt2);
return ans;
}
int main()
{
n=read();
for(int i=;i<=n;i++)
{
pos=read();
cnt++;cnt[v]=query(pos)+;
cnt[sz]=;cnt[rnd]=rand();
ins(root,cnt,pos);
printf("%d\n",root[mx]);
}
return ;
}

【树状数组 离线】

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+;
int n,id,cnt,f[N],ans[N],a[N],num[N],bit[N];
int read()
{
int x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int lowbit(int x){return x&(-x);}
void ins(int x){while(x<=n)bit[x]--,x+=lowbit(x);}
int pos(int x)
{
int now=,ans=;
for(int i=;i>=;i--)
{
now+=(<<i);
if(now<n&&ans+bit[now]<x)ans+=bit[now];
else now-=(<<i);
}
return now+;
}
int main()
{
n=read();
for(int i=;i<=n;i++)
{
a[i]=read();bit[i]++;
if(i+lowbit(i)<=n)bit[i+lowbit(i)]+=bit[i];
}
for(int i=n;i>=;i--)
id=pos(a[i]+),num[id]=i,ins(id);
for(int i=;i<=n;i++)
{
id=lower_bound(f+,f+cnt+,num[i])-f;
if(id>cnt)f[++cnt]=num[i];
else f[id]=num[i];
ans[num[i]]=id;
}
for(int i=;i<=n;i++)ans[i]=max(ans[i],ans[i-]),printf("%d\n",ans[i]);
return ;
}

【bzoj 3173】[Tjoi2013]最长上升子序列的更多相关文章

  1. BZOJ 3173: [Tjoi2013]最长上升子序列

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1524  Solved: 797[Submit][St ...

  2. Bzoj 3173: [Tjoi2013]最长上升子序列 平衡树,Treap,二分,树的序遍历

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1183  Solved: 610[Submit][St ...

  3. BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )

    因为是从1~n插入的, 慢插入的对之前的没有影响, 所以我们可以用平衡树维护, 弄出最后的序列然后跑LIS就OK了 O(nlogn) --------------------------------- ...

  4. BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1613  Solved: 839[Submit][St ...

  5. bzoj 3173 [Tjoi2013]最长上升子序列 (treap模拟+lis)

    [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2213  Solved: 1119[Submit][Status] ...

  6. BZOJ 3173 [Tjoi2013] 最长上升子序列 解题报告

    这个题感觉比较简单,但却比较容易想残.. 我不会用树状数组求这个原排列,于是我只好用线段树...毕竟 Gromah 果弱马. 我们可以直接依次求出原排列的元素,每次找到最小并且最靠右的那个元素,假设这 ...

  7. BZOJ 3173: [Tjoi2013]最长上升子序列 (线段树+BIT)

    先用线段树预处理出每个数最终的位置.然后用BIT维护最长上升子序列就行了. 用线段树O(nlogn)O(nlogn)O(nlogn)预处理就直接倒着做,每次删去对应位置的数.具体看代码 CODE #i ...

  8. bzoj 3173: [Tjoi2013]最长上升子序列【dp+线段树】

    我也不知道为什么把题看成以插入点为结尾的最长生生子序列--还WA了好几次 先把这个序列最后的样子求出来,具体就是倒着做,用线段树维护点数,最开始所有点都是1,然后线段树上二分找到当前数的位置,把这个点 ...

  9. BZOJ 3173: [Tjoi2013]最长上升子序列 Splay

    一眼切~ 重点是按照 $1$~$n$ 的顺序插入每一个数,这样的话就简单了. #include <cstdio> #include <algorithm> #define N ...

  10. 3173: [Tjoi2013]最长上升子序列

    原题:http://www.lydsy.com/JudgeOnline/problem.php?id=3173 题解:促使我写这题的动力是,为什么百度遍地是Treap,黑人问号??? 这题可以用线段树 ...

随机推荐

  1. [ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)

    这两道题思路比较像,所以把他们放到一块. [ZJOI2016]小星星 题目描述 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星. ...

  2. 【mysql】mysql常用语句

    返回不重复数据 SELECT DISTINCT user_name,vistor_username FROM KY_FEED_VISTOR WHERE user_name='shenhy' 单独的di ...

  3. js,jquery 获取滚动条高度和位置, 元素距顶部距离

    一,获取滚动条高度和位置 jQuery 获取览器显示区域的高度: $(window).height();  获取浏览器显示区域的宽度:$(window).width(); 获取页面的文档高度:$(do ...

  4. 【洛谷P3917】异或序列

    题目大意:给定一个长度为 N 的序列,每个位置有一个权值,求 \[\sum\limits_{1\le i\le j\le n}(a_i\oplus a_{i+1}...\oplus a_j)\] 的值 ...

  5. MariaDB安装及基本配置

    MariaDB安装及基本配置(CentOS6.9) 数据库基础概念 数据库(Database, DB)是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. DBMS: Database ...

  6. bzoj1497 最大获利(最大权闭合子图)

    题目链接 思路 对于每个中转站向\(T\)连一条权值为建这个中转站代价的边.割掉这条边表示会建这个中转站. 对于每个人向他的两个中转站连一条权值为\(INF\)的边.然后从\(S\)向这个人连一条权值 ...

  7. 关于dp(背包)

    有关背包,我这几天可是尽受其苦(不得不靠我聪颖的背诵代码的大脑来进行一波操作) Step 1      01背包 关于01背包的主要代码: ;j<=m;j++) { for(int i=n;i& ...

  8. 第二十九篇-Fragment动态用法

    效果图: 上节学习了静态添加Fragment的方法,这节学习动态添加方法. 主页面 layout.xml Fragment页面 layout2.xml 实现功能,当点击主页面的button时,将Fra ...

  9. 第五篇-以显式意图(Explicit Intent)跳往其它Activity

    此项目基于第四篇. Intent(意图) Explicit Intent(显式意图): 清楚指明需要前往的Activity的名称 用于APP内部的连接 Inplicit Intent(隐式意图): 不 ...

  10. OmniPlan,一款让你无法自拔的项目管理工具(仅适用于MAC系统)

      OmniPlan 大家都知道Windows系统可以使用project来方便的管理跟踪项目的各项任务,那么Mac系统有没有这样专业级的项目管理软件了?答案是有,今天给大家推荐的Mac系统下的项目管理 ...