FHQ_Treap 太神辣

蒟蒻初学FHQ_Treap,于是来到了这道略显板子的题目

因为Treap既满足BST的性质,又满足Heap的性质,所以,对于这道题目,我们可以将以往随机出的额外权值转化为每一个位置的高度,这样我们就可以利用小根堆的性质,甚至连\(Split\)操作都可以省略掉,就可以AC这道题目

步骤:

1.首先找到现在的根节点,即当前高度最低的位置

2.根据Treap的性质,我们只需要将其左子树打一个反转的标记,然后将根节点删除,将其左右两个子树合并,那么,新的子节点就是我们接下来需要的第2小高度的位置

3.重复1,2操作,这个题目就完结撒花辣!!

但是高度有可能是相同的,题目中又要求取靠前的那一个,于是我们将所有的数乘上n,再加上i,这样就可以有效避免这一个问题。

愿望总是美好的


[CQOI2014]排序机械臂愉快的过掉了,但另外一道相同的题目却过不了(robotic sort)。然后,有dalao指出,这样的做法,只要数据是单调的,就会被卡成\(O(n^2)\)

于是,通过查阅资料,我们可以使用一种神奇的方法——笛卡尔树,这样就可以有效避免这个问题。

对于\(Treap\)来说,我们可以将每一个节点的信息简化为一个二元组\((val,rand)\),意义一看便知

我们按照val的顺序进行插入,而在本题中,val即初始位置1~n,所以不用重新排序。

我们可以维护一个单调栈,从而有效解决这个问题。

对于每一个节点,我们将栈中大于当前节点rand值的节点全部弹出,将他们挂在当前节点的左儿子上,然后再把连同当前节点一起的这一棵树挂在弹完所有值之后的栈顶节点的右儿子上,这样就可以构建出一颗相对平衡的Treap。

用通俗的话讲,对于当前节点u,我们只考虑将其放在最右边的这一条链上,如果他比所有节点的rand值都大,那么当然顺理成章的放在最右边,如果没有,我们就考虑同时维护BST与Heap的性质,于是就有了我们上面的做法。

贴代码啦~

//短短70行解决战斗
#include<bits/stdc++.h>
using namespace std;
const long long maxn=5e5+10;
long long inline read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
long long son[maxn][2],val[maxn],rnd[maxn],siz[maxn],cnt,rt,tag[maxn];
inline void upd(long long t){siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;}
inline void down(long long x)
{
if(tag[x])
{
swap(son[x][0],son[x][1]);
if(son[x][0]) tag[son[x][0]]^=1;
if(son[x][1]) tag[son[x][1]]^=1;
tag[x]=0;
}
}
inline long long init(long long x,long long qaq)
{
++cnt,val[cnt]=x,siz[cnt]=1,rnd[cnt]=qaq;
return cnt;
}
inline long long merge(long long x,long long y)
{
if(!x||!y) return x+y;
if(rnd[x]<rnd[y])
{
down(x),son[x][1]=merge(son[x][1],y),upd(x);
return x;
}
else
{
down(y),son[y][0]=merge(x,son[y][0]),upd(y);
return y;
}
}
struct cc{
long long num,id;
}a[maxn];
int main()
{
srand(time(0));
long long opt,n,m,l,r,x,y,z;
n=read();
stack<int> q;
for(int i=1;i<=n;++i)
{
scanf("%lld",&rnd[i]),rnd[i]=rnd[i]*n+i,val[i]=i,siz[i]=1;
while((!q.empty())&&rnd[i]<rnd[q.top()])
son[i][0]=q.top(),q.pop(),upd(son[i][0]);
if(!q.empty()) son[q.top()][1]=i;
q.push(i);
}
while(!q.empty()) rt=q.top(),upd(q.top()),q.pop();
for(int i=1;i<=n;++i)
{
down(rt);
printf("%lld ",siz[son[rt][0]]+i);
l=son[rt][0],r=son[rt][1];
son[rt][0]=son[rt][1]=0;
tag[l]^=1;
rt=merge(l,r);
}
printf("\n");
return 0;
}

洛谷 P4402 BZOJ1552 / 3506 [Cerc2007]robotic sort 机械排序的更多相关文章

  1. [UVA1402]Robotic Sort;[SP2059]CERC07S - Robotic Sort([洛谷P3165][CQOI2014]排序机械臂;[洛谷P4402][Cerc2007]robotic sort 机械排序)

    题目大意:一串数字,使用如下方式排序: 先找到最小的数的位置$P_1$,将区间$[1,P_1]$反转,再找到第二小的数的位置$P_2$,将区间$[2,P_2]$反转,知道排序完成.输出每次操作的$P_ ...

  2. BZOJ1552/3506 [Cerc2007]robotic sort

    Splay 与之前不同的是如果你仅仅是翻转左右区间的话可以在find里面做因为对他有影响的子树在做之前一定在他的上面从上到下搜索的过程可以把rever做了. 但这道题要求我们输出转换之前的,因此不能保 ...

  3. 【BZOJ1552】[Cerc2007]robotic sort Splay

    [BZOJ1552][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N ...

  4. 【BZOJ-1552&3506】robotic sort&排序机械臂 Splay

    1552: [Cerc2007]robotic sort Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 806  Solved: 329[Submit][ ...

  5. 【bzoj1552】[Cerc2007]robotic sort

    题目描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号. 输出 输出共一行,N个用空格隔开的 ...

  6. 【BZOJ】1552/3506 [Cerc2007]robotic sort

    [算法]splay [题解] splay维护序列,用权值(离散化)作为编号.每次找第i小的话直接找对应编号splay即可. 但是这样splay没有下传翻转标记?直接暴力找到路径然后从根到改结点push ...

  7. 【bzoj1552/3506】[Cerc2007]robotic sort splay翻转,区间最值

    [bzoj1552/3506][Cerc2007]robotic sort Description Input 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000. ...

  8. [BZOJ1552][Cerc2007]robotic sort

    [BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...

  9. BZOJ 1552: [Cerc2007]robotic sort( splay )

    kpm大神说可以用块状链表写...但是我不会...写了个splay.... 先离散化 , 然后splay结点加个min维护最小值 , 就可以了... ( ps BZOJ 3506 题意一样 , 双倍经 ...

随机推荐

  1. Python+Selenium学习笔记10 - send_keys上传文件

    在火狐浏览器上传文件 上传前,同一个HTML文件在火狐和Edge浏览器显示有些不同 这是Firefox浏览器的显示 这是Edge浏览器 上传后 1 # coding = utf-8 2 3 from ...

  2. 执行Selenium后在temp目录下产生临时文件scoped_dir chrome_BITS

    环境:Windows selenium 3.141.0 Python 3.8.10 Chrome 90.0.4430.212 ChromeDriver 90.0.4430.24 最近发现执行完Sele ...

  3. double类型数据有的时候null的判断

    double不是Double,无法通过 == null来判断 如何进行double的null判断呢 double avg = avg.getValue() // 此时不会报错 // 通过如下进行判断 ...

  4. 新的微芯片MCU增加了来自外部闪存的安全引导保护

    新的微芯片MCU增加了来自外部闪存的安全引导保护 New Microchip MCU Adds Secure Boot Protection from External Flash 对于从外部SPI闪 ...

  5. 开发掉坑(二)前端静态资源 Uncaught SyntaxError: Unexpected token <

    某天,有同学反馈后台管理系统出现静态资源无法加载的问题. 复现如下: 进入首页. 点击侧边栏某个子功能,静态资源可正常访问到. 等待10分钟左右,点击侧边栏其他子功能,无法访问到静态资源. 查看控制台 ...

  6. MySQL索引简介(转)

    一.为什么用索引例:先假设有一张表,表的数据有10W条数据,其中有一条数据是nickname='css',如果要拿这条数据的话需要写的sql是 SELECT * FROM award WHERE ni ...

  7. ld-linux-x86-64消耗大量的CPU

    1.现象: 服务器CPU使用率很高 top查看cpu使用进程: 2.进程用户是oracle,根据spid查看是否是数据库进程,经过查询发现:不是数据库内部的进程 select a.sql_id,a.s ...

  8. Springboot集成Spring Security实现JWT认证

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 Spring Security作为成熟且强大的安全框架,得到许多大厂的青睐.而作为前后端分离的SSO方案,JWT ...

  9. 散列数据结构以及在HashMap中的应用

    1. 为什么需要散列表? 对于线性表和链表而言,访问表中的元素,时间复杂度均为O(n).即便是通过树结构存储数据,时间复杂度也为O(logn).那么有没有一种方式可以将这个时间复杂度降为O(1)呢?当 ...

  10. Dagger2入门,以初学者角度

    2016-12-21 更新:添加@Subcomponent注解以及Lazy与Provider的使用,本文基本完结!如果有好的建议请提出,感谢大家的支持,谢谢 依赖注入 Dagger2是Android中 ...