最长上升子序列 bzoj-3173

    题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度。

    注释:1<=n<=10,000,开始序列为空。

      具体的非旋转Treap的讲解:讲解链接

      想法:显然,我们发现,我每次加入的数一定是当前序列中最大的,所以,刚刚加入的i,要么是当前序列中LIS的结尾,要么不属于LIS。根据这个性质,我们想到:在Treap中维护这样的性质,就是维护每个数加入节点的编号。然后,我们更新新节点的方式就是它的左子树和右子树的LIS取最大+1。其实最重要的就是如何加入这个新的节点?我们引进非旋转Treap。

        非旋转Treap在结构上和Treap一样,都是维护平衡的BST。但是,非旋转Treap在实现上更加暴力和简单。有两个操作,撕裂和合并。

        撕裂?就是去除BST上的一条边,使得原来的非旋转Treap变成两颗树。这样我们就可以对于撕裂开的新子树进行一些单独的处理。例如我们可以撕裂两次,得到一段区间,那么在进行区间反转时就可以仅仅维护一段子树就可以了。

        合并?就是将撕裂之后的子树进行合并即可。这样的话我们对于BST节点的一个权值是随机的,所以我们在合并时还要维护Treap的基本性质。

      这道题的实现和理解无疑是非旋转Treap的裸题,但是非旋转Treap强大的地方已经得到体现。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 300100
#define mp make_pair
using namespace std;
typedef pair<int,int> par;
int n;
int maxx[N],lis[N],size[N],ls[N],rs[N],key[N];
//maxx表示当前节点子树的LIS的长度
//lis表示当前子树中以当前节点结尾的不下降子序列长度
int root;
void update(int x)//这是向上更新
{
maxx[x]=lis[x];
size[x]=size[ls[x]]+size[rs[x]]+1;
maxx[x]=max(maxx[x],max(maxx[ls[x]],maxx[rs[x]]));
}
int lson,rson;
par split(int x,int k)//撕裂操作,返回的是撕裂后两棵新树的根节点,用pair来存储
{
if(!k) return mp(0,x);
lson=ls[x],rson=rs[x];par t;
if(k==size[ls[x]])
{
ls[x]=0;update(x);
return mp(lson,x);
}
if(k==size[ls[x]]+1)
{
rs[x]=0;update(x);
return mp(x,rson);
}
if(k<size[ls[x]])
{
t=split(lson,k);
ls[x]=t.second;update(x);
return mp(t.first,x);
}
t=split(rson,k-size[ls[x]]-1);
rs[x]=t.first;update(x);
return mp(x,t.second);
}
int merge(int x,int y)//合并操作,返回的是合并之后的新树的根节点
{
if(!x|!y)
{
return x|y;
}
if(key[x]<key[y])
{
ls[y]=merge(x,ls[y]);update(y);
return y;
}
rs[x]=merge(rs[x],y);update(x);
return x;
}
int main()
{
scanf("%d",&n);
int ans=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
size[i]=1;
key[i]=rand()*rand();
par t1;
t1=split(root,x);
lis[i]=maxx[i]=maxx[t1.first]+1;
ans=max(ans,lis[i]);
printf("%d\n",ans);
root=merge(merge(t1.first,i),t1.second);
}
return 0;
}

    小结:非旋转Treap相较于Treap所涉及的范围更广,但虽然代码量有所下降,但是细节更多,难度更大。

      错误:split的!k是要进行特判的,不然会死递归。

[bzoj3173]最长上升子序列_非旋转Treap的更多相关文章

  1. [bzoj1500][NOI2005]维修数列_非旋转Treap

    维修数列 bzoj-1500 NOI-2005 题目大意:给定n个数,m个操作,支持:在指定位置插入一段数:删除一个数:区间修改:区间翻转.查询:区间和:全局最大子序列. 注释:$1\le n_{ma ...

  2. [bzoj4864][BeiJing2017Wc]神秘物质_非旋转Treap

    神秘物质 bzoj-4864 BeiJing-2017-Wc 题目大意:给定一个长度为n的序列,支持插入,将相邻两个元素合并并在该位置生成一个指定权值的元素:查询:区间内的任意一段子区间的最大值减最小 ...

  3. [bzoj1552\bzoj2506][Cqoi2014]robotic sort 排序机械臂_非旋转Treap

    robotic sort 排序机械臂 bzoj-1552 bzoj-2506 Cqoi-2014 题目大意:给定一个序列,让你从1到n,每次将[1,p[i]]这段区间反转,p[i]表示整个物品权值第i ...

  4. [bzoj1861][Zjoi2006]Book 书架_非旋转Treap

    Book 书架 bzoj-1861 Zjoi-2006 题目大意:给你一个序列,支持:将指定编号的元素抽出,放到序列顶(底):将指定编号元素左右篡位:查询指定编号元素位置:查询指定数量位置元素编号. ...

  5. [BZOJ3173]最长上升子序列

    Problem 给你n个数A1~An,每次将i插入第Ai位后,最后输出每次插入后这个数列的最长上升子序列 Solution 这道题非常的妙.首先如果新加入的这个数构成了最长上升子序列,由于在它插入之前 ...

  6. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  7. BZOJ3224普通平衡树——非旋转treap

    题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...

  8. BZOJ1500[NOI2005]维修数列——非旋转treap

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 输入 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初 ...

  9. BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*

    BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...

随机推荐

  1. ASI通讯协议——ASI2x1

    通讯协议--ASI2x1 基本功能描述 计算机或控制器通过以太网口或者RS232接口发出指令,包括查询指令,切换指令等,主机箱中的控制板在收到这些指令之后,将这些数据通过485总线转发给对应的主板,并 ...

  2. HTML多表头表格

    1.多表头表格代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  3. TypeError: Error #1034: 强制转换类型失败:无法将 "0.49" 转换为 mx.graphics.IFill。

    1.错误描述 TypeError: Error #1034: 强制转换类型失败:无法将 "0.49" 转换为 mx.graphics.IFill. at mx.charts.ser ...

  4. 关于tween.js测试介绍

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>t ...

  5. xml的Dom4j解析规则

    一,xml的样本 <?xml version="1.0" encoding="utf-8"?> <contactList> <co ...

  6. TensorLayer官方中文文档1.7.4:API – 可视化

    API - 可视化¶ TensorFlow 提供了可视化模型和激活输出等的工具 TensorBoard. 在这里,我们进一步提供一些可视化模型参数和数据的函数. read_image(image[,  ...

  7. [AH/HNOI2017]礼物

    \[推推公式,即求\Sigma^{n}_{i=1} (x_{i+k}-y_i+c)^2最小,c范围为[-m, m]\] \[拆开,就是\Sigma x_i^2 + \Sigma y_i^2 + n * ...

  8. angularJs $mdDialog和$uibModal弹框关闭传值

    $mdDialog以一个点击button按钮出现弹框为例: $scope.btn=function($event,row){ var dScope = $scope.$new(true); dScop ...

  9. eclipse 精确查询

    ---恢复内容开始--- ctrl+H(一般都是这个,如果无效看你的自定义快捷键) 输入\b 查询的字符串 \b   后面的正则表达式选框必须选

  10. 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作

    前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...