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

Solution

设$f[i]$表示以$i$数字为结尾的最长上升子序列长度。

可以发现插入一个数的时候只有当前这个数的$f$会变化,也就是当前这个数前面一段的$max(f)+1$。

用$Splay$维护一下就好了。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#define N (100009)
using namespace std; int n,m,p,ans,Root;
int Father[N],Son[N][],f[N],Max[N],Size[N]; inline int read()
{
int x=,w=; char c=getchar();
while (c<'' || c>'') {if (c=='-') w=-; c=getchar();}
while (c>='' && c<='') x=x*+c-'', c=getchar();
return x*w;
} int Get(int x)
{
return Son[Father[x]][]==x;
} void Pushup(int x)
{
Max[x]=f[x];
if (Son[x][]) Max[x]=max(Max[x],Max[Son[x][]]);
if (Son[x][]) Max[x]=max(Max[x],Max[Son[x][]]);
Size[x]=Size[Son[x][]]+Size[Son[x][]]+;
} void Rotate(int x)
{
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Father[fa]=x; Son[fa][wh]=Son[x][wh^];
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Father[x]=fafa; Son[x][wh^]=fa;
Pushup(fa); Pushup(x);
} void Splay(int x,int tar)
{
for (int fa; (fa=Father[x])!=tar; Rotate(x))
if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
} int Next(int now)
{
if (!Son[now][]) return now;
now=Son[now][];
while (Son[now][]) now=Son[now][];
return now;
} int Findkth(int x)
{
int now=Root;
while ()
if (x<=Size[Son[now][]]) now=Son[now][];
else
{
x-=Size[Son[now][]];
if (x==) {Splay(now,); return now;}
x--; now=Son[now][];
}
} int main()
{
n=read();
Max[]=Max[n+]=f[]=f[n+]=-2e9;
Father[n+]=; Son[][]=n+;
for (int i=; i<=n+; ++i) Size[i]=;
Size[]=; Root=;
for (int i=; i<=n+; ++i)
{
p=read(); p=Findkth(p+);
int nxt=Next(Root); Splay(,);
if (nxt!=) Splay(nxt,);
f[i]=Max[Son[nxt][]]+;
ans=max(ans,f[i]);
printf("%d\n",ans); Splay(p,);
if (nxt!=p) Splay(nxt,p);
Father[i]=nxt; Son[nxt][]=i;
Max[i]=f[i];
Splay(i,);
}
}

BZOJ3173:[TJOI2013]最长上升子序列(Splay)的更多相关文章

  1. [BZOJ3173][Tjoi2013]最长上升子序列

    [BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...

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

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

  3. bzoj3173[Tjoi2013]最长上升子序列 平衡树+lis

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2253  Solved: 1136[Submit][S ...

  4. bzoj3173: [Tjoi2013]最长上升子序列(树状数组+二分倒推)

    3173: [Tjoi2013]最长上升子序列 题目:传送门 题解:  好题! 怎么说吧...是应该扇死自己...看错了两次题: 每次加一个数的时候,如果当前位置有数了,是要加到那个数的前面,而不是直 ...

  5. BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)

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

  6. bzoj千题计划316:bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3173 插入的数是以递增的顺序插入的 这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某 ...

  7. bzoj3173: [Tjoi2013]最长上升子序列(fhqtreap)

    这题用fhqtreap可以在线. fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影 ...

  8. BZOJ3173 TJOI2013最长上升子序列(splay)

    容易发现如果求出最后的序列,只要算一下LIS就好了.序列用平衡树随便搞一下,这里种一棵splay. #include<iostream> #include<cstdio> #i ...

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

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

随机推荐

  1. C# 字符串首字符大写

    我找到一些把字符串首字符大写的方法. 假如需要把字符串 "red" 转换为 "Red",把 "red house" 转为 "Red ...

  2. Bower前端模块管理器

    cnpm install bower -g 安装bower bower install jquery //bower会自动去网上找到最新版本的jquery bower uninstall jquery ...

  3. C#图片文字识别

    图片识别的技术到几天已经很成熟了,只是相关的资料很少,为了方便在此汇总一下(C#实现),方便需要的朋友查阅,也给自己做个记号. 图片识别的用途:很多人用它去破解网站的验证码,用于达到自动刷票或者是批量 ...

  4. 编程输出杨辉三角的前10行---多维数组的应用---java实现

    import java.util.Scanner;public class yanghui{ public static void main(String[] args){  Scanner sc=n ...

  5. Cookies读写

    /** * Minified by jsDelivr using Terser v3.14.1. * Original file: /npm/js-cookie@2.2.0/src/js.cookie ...

  6. 深入理解Java虚拟机--阅读笔记二

    垃圾收集器与内存分配策略 一.判断对象是否已死 1.垃圾收集器在对堆进行回收前,要先判断对象是否已死.而判断的算法有引用计数算法和可达性分析算法: 2.引用计数算法是给对象添加引用计数器,有地方引用就 ...

  7. 分机号-2015决赛C语言C组第一题

    标题:分机号 X老板脾气古怪,他们公司的电话分机号都是3位数,老板规定,所有号码必须是降序排列,且不能有重复的数位.比如: 751,520,321 都满足要求,而, 766,918,201 就不符合要 ...

  8. 前m大的数(hdu1280)

    前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  9. java如何正确停止一个线程

    Thread类中有start(), stop()方法,不过stop方法已经被废弃掉. 平时其实也有用过,共享一个变量,相当于标志,不断检查标志,判断是否退出线程 如果有阻塞,需要使用Thread的in ...

  10. linux7 安装GitLab

    1.安装Linux虚拟机-- 安装后配置a.停止防火墙# systemctl stop firewalld.service# systemctl disable firewalld.service# ...