Book 书架 bzoj-1861 Zjoi-2006

题目大意:给你一个序列,支持:将指定编号的元素抽出,放到序列顶(底);将指定编号元素左右篡位;查询指定编号元素位置;查询指定数量位置元素编号。

注释:$1\le n,m\le 8\cdot 10^4$

想法:非旋转Treap裸题

需要注意的就是那个反复横跳的操作,只需要把指定元素和它接下来要交换的元素都split出来,然后一一合并即可。

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

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 80010
#define mp make_pair
using namespace std;
typedef pair<int,int> par;
int n,m,root;
int ls[N],rs[N],size[N],key[N],fa[N];
inline void pushup(int x)
{
size[x]=size[ls[x]]+size[rs[x]]+1;
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(key[x]>key[y])
{
rs[x]=merge(rs[x],y);fa[rs[x]]=x;
pushup(x); return x;
}
ls[y]=merge(x,ls[y]);fa[ls[y]]=y;
pushup(y); return y;
}
par split(int x,int k)
{
if(!k) return mp(0,x);
int lson=ls[x],rson=rs[x];
if(k==size[lson])
{
ls[x]=0;pushup(x);
fa[lson]=0;
return mp(lson,x);
}
if(k==size[lson]+1)
{
rs[x]=0;pushup(x);
fa[rson]=0;
return mp(x,rson);
}
if(k<size[lson])
{
par t=split(lson,k);
ls[x]=t.second;fa[ls[x]]=x;pushup(x);
return mp(t.first,x);
}
par t=split(rson,k-size[ls[x]]-1);
rs[x]=t.first;fa[rs[x]]=x;pushup(x);
return mp(x,t.second);
}
int getid(int x)
{
int flag=1,t=x,ans=0;
while(t)
{
if(flag)ans+=size[ls[t]]+1;
flag=(t==rs[fa[t]]);
t=fa[t];
}
return ans-1;
}
int find(int x)
{
x--;int t=root;
while(1)
{
if(x==size[ls[t]]) return t;
if(x<size[ls[t]]) t=ls[t];
else x-=size[ls[t]]+1,t=rs[t];
}
}
int main()
{
cin >> n >> m ;
for(int x,i=1;i<=n;i++)
{
scanf("%d",&x);
size[x]=1,key[x]=rand()*rand();
root=merge(root,x);
}
char flag[10];
for(int x,y,i=1;i<=m;i++)
{
scanf("%s",flag);
if(flag[0]=='T')
{
scanf("%d",&x);
int id=getid(x);
par t2=split(root,id+1),t1=split(t2.first,id);
root=merge(t1.second,merge(t1.first,t2.second));
}
else if(flag[0]=='B')
{
scanf("%d",&x);
int id=getid(x);
par t2=split(root,id+1),t1=split(t2.first,id);
root=merge(merge(t1.first,t2.second),t1.second);
}
else if(flag[0]=='I')
{
scanf("%d%d",&x,&y);
if(!y)continue;
if(y==-1)
{
int id=getid(x);
par t3=split(root,id+1),t2=split(t3.first,id),t1=split(t2.first,id-1);
root=merge(merge(merge(t1.first,t2.second),t1.second),t3.second);
}
else
{
int id=getid(x);
par t3=split(root,id+2),t2=split(t3.first,id+1),t1=split(t2.first,id);
root=merge(merge(merge(t1.first,t2.second),t1.second),t3.second);
}
}
else if(flag[0]=='A')
{
scanf("%d",&x);
printf("%d\n",getid(x));
}
else
{
scanf("%d",&x);
printf("%d\n",find(x));
}
}
return 0;
}

小结:非旋转Treap就是比splay优(傲娇脸)

[bzoj1861][Zjoi2006]Book 书架_非旋转Treap的更多相关文章

  1. [bzoj3173]最长上升子序列_非旋转Treap

    最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...

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

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

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

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

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

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

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

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

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

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

  7. 非旋转Treap:用运行时间换调试时间的有效手段

    非旋转Treap:用运行时间换调试时间的有效手段   Hello大家好,我们今天来聊一聊非旋转Treap. 相信各位或多或少都做过些序列上的问题.如果水题我们考虑暴力:不强制在线我们可能用过莫队和待修 ...

  8. [BZOJ1861][Zjoi2006]Book 书架

    [BZOJ1861][Zjoi2006]Book 书架 试题描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候 ...

  9. 关于非旋转treap的学习

    非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为\(logn\) split 作用:将原 ...

随机推荐

  1. dp状态压缩

    dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状 ...

  2. codeforces 916E Jamie and Tree dfs序列化+线段树+LCA

    E. Jamie and Tree time limit per test 2.5 seconds memory limit per test 256 megabytes input standard ...

  3. [NOIP 2014] 生活大爆炸版石头剪刀布

    [题目链接] http://uoj.ac/problem/15 [算法] 按题意模拟即可[代码] #include<bits/stdc++.h> using namespace std; ...

  4. 第2章 安装Nodejs Nodejs基础 课程介绍

    因为你做任何Nodejs应用,底层无非都是通过调用这些既有的开放的接口,来完成相应的功能.这个要注意,不同版本的Nodejs,接口不一定相同.甚至是相同的接口,使用规范也有区别.我们以这个版本来过这些 ...

  5. C++ this指针 全部

    在每一个成员函数中都包含一个特殊的指针,这个指针的名字是固定的.叫做this.它是指向本类对象的指针,它的值是当前被调用的成员函数所在的对象的起      始地址.例如:当调用成员函数a.volume ...

  6. bzoj2763: [JLOI2011]飞行路线(分层图spfa)

    2763: [JLOI2011]飞行路线 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3234  Solved: 1235[Submit][Stat ...

  7. hdu3853LOOPS(概率与期望dp)

    LOOPS Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 125536/65536 K (Java/Others)Total Sub ...

  8. 原生JS---2

    js中的程序控制语句 常见的程序有三种执行结构: 1. 顺序结构 2. 分支结构 3. 循环结构 顺序结构:程序从第一行开始执行,按顺序执行到最后一行 分支结构:就像一条岔路口,必须选择且只能选择其中 ...

  9. [Apple开发者帐户帮助]五、管理标识符(1)注册应用程序ID

    一个应用程序ID标识的配置设定档中的应用程序.它是一个由两部分组成的字符串,用于标识来自单个开发团队的一个或多个应用程序.有两种类型的应用程序ID:用于单个应用程序的显式应用程序ID,以及用于一组应用 ...

  10. Docker容器的使用和连接

    在上一篇文章<Docker从安装部署到Hello World>介绍了如何在CentOS7上安装Docker.这篇文章主要介绍一下Docker容器的使用和连接. vDocker 容器使用 1 ...