「模板」 FHQ_Treap 区间翻转

<题目链接>


没有旋转的 Treap 实现区间操作的功能,很好理解,也很好写,只是速度不算太快。

对于要翻转的区间,把整棵 Treap(存有区间 \([1,n]\) 的信息)Split 成 \([1,l-1]\)、\([l,r]\)、\([r+1,n]\) 三部分,给中间部分的根节点打上标记,再一边下传标记一边 Merge 回来。

注意 Split 时,要按元素个数,不能按权值,因为元素个数可以通过维护节点信息的 size 域而直接得到,但随着区间的翻转,权值会乱套。

一定注意先推标记!!先推标记!!先推标记!!

就因为标记推晚了,我调了一天。

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using std::swap;
const int MAXN=100010;
int n,m;
class FHQ_Treap
{
public:
FHQ_Treap(void)
{
rt=cnt=0;
memset(a,0,sizeof a);
}
void Insert(int x)
{
s[++cnt]=node(x,Random(),1);
Merge(rt,rt,cnt);
}
void Reverse(int x,int y)
{
int l=0,r=0,t=0;
Split(rt,x-1,l,t),Split(t,y-x+1,t,r);
s[t].lazy^=1,Merge(l,l,t),Merge(rt,l,r);
}
void Print(void)
{
DFS(rt),putchar('\n');
}
private:
bool a[MAXN];
int rt,cnt;
struct node
{
int v,p,size,lazy,c[2];
node(int _v=0,int _p=0,int _size=0)
{
v=_v,p=_p,size=_size,lazy=0;
memset(c,0,sizeof c);
}
}s[MAXN];
int Random(void)
{
int x;
while(a[x=rand()%MAXN]);
a[x]=1;
return x;
}
void Update(int i)
{
s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
}
void PushDown(int i)
{
int &l=s[i].c[0],&r=s[i].c[1];
swap(l,r);
if(l)
s[l].lazy^=1;
if(r)
s[r].lazy^=1;
s[i].lazy=0;
}
void Split(int i,int x,int &l,int &r)
{
if(!i)
{
l=r=0;
return;
}
if(s[i].lazy)
PushDown(i);
int t=s[s[i].c[0]].size+1;
if(x<t)
Split(s[r=i].c[0],x,l,s[i].c[0]);
else
Split(s[l=i].c[1],x-t,s[i].c[1],r);
Update(i);
}
void Merge(int &i,int l,int r)
{
if(!l || !r)
{
i=l|r;
return;
}
if(s[l].p>s[r].p)
{
if(s[l].lazy)
PushDown(l);
Merge(s[i=l].c[1],s[l].c[1],r);
}
else
{
if(s[r].lazy)
PushDown(r);
Merge(s[i=r].c[0],l,s[r].c[0]);
}
Update(i);
}
void DFS(int i)
{
if(s[i].lazy)
PushDown(i);
if(s[i].c[0])
DFS(s[i].c[0]);
printf("%d ",s[i].v);
if(s[i].c[1])
DFS(s[i].c[1]);
}
}T;
int main(int argc,char *argv[])
{
srand((unsigned)time(NULL));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)
T.Insert(i);
for(int i=1,l,r;i<=m;++i)
{
scanf("%d %d",&l,&r);
T.Reverse(l,r);
}
T.Print();
return 0;
}

谢谢阅读。

「模板」 FHQ_Treap 区间翻转的更多相关文章

  1. 「模板」 FHQ_Treap

    「模板」 FHQ_Treap 我也是偶然发现我还没发过FHQ_Treap的板子. 那就发一波吧. 这个速度实在不算快,但是不用旋转,并且好写. 更重要的是,Splay 可以做的事情它都可以做!比如区间 ...

  2. 「模板」 线段树——区间乘 && 区间加 && 区间求和

    「模板」 线段树--区间乘 && 区间加 && 区间求和 原来的代码太恶心了,重贴一遍. #include <cstdio> int n,m; long l ...

  3. 「模板」 树链剖分 HLD

    「模板」 树链剖分 HLD 不懂OOP的OIer乱用OOP出人命了. 谨此纪念人生第一次类套类. 以及第一次OI相关代码打过200行. #include <algorithm> #incl ...

  4. 「模板」「讲解」Treap名次树

    Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...

  5. 「LuoguP2434」 [SDOI2005]区间(贪心

    Description 现给定n个闭区间[ai, bi],1<=i<=n.这些区间的并可以表示为一些不相交的闭区间的并.你的任务就是在这些表示方式中找出包含最少区间的方案.你的输出应该按照 ...

  6. LG3205/BZOJ1996 「HNOI2010」合唱队 区间DP

    区间DP 区间DP: 显然是一个区间向左右拓展形成的下一个区间,具有包含关系,所以可以使用区间DP. 状态设计: 考虑和关路灯一样设计状态 因为不知道当前这个区间是从哪个区间拓展而来,即不知道这个区间 ...

  7. 「模板」Splay

    代码说明 对于一些变量进行说明: 变量名 说明 rt 树根 ff[u] 点 \(u\) 的父节点,特别地, ff[rt]=0 ch[u][0|1] 点 \(u\) 的 左/右儿子 siz[u] 点 \ ...

  8. 「模板」AC自动机

    目录 说明 普通版本 询问更改版 拓扑优化版本 说明 这篇博客只挂模板,具体分析请膜拜大佬 hyfhaha 大佬. 普通版本 题目传送门 #include<cstdio> #include ...

  9. 「模板」可持久化 HFQ-Treap

    老师用的是静态数组的写法,开了很多数组- 其实个人更倾向于 struct 或者用 class 封装起来. 但是鉴于太难打 好吧,是我懒得打. 然后就借鉴了老师的模板,写出了属于自己的 压行 风格. 代 ...

随机推荐

  1. 蓝牙ble数据转语音实现Android AudioRecord方法推荐

    蓝牙ble数据转语音实现Android AudioRecord方法推荐 教程  欢迎走进zozo的学习之旅. 概述 蓝牙BLE又称bluetooth smart,主打的是低功耗和快速链接,所以在支持的 ...

  2. c# 编译的dll看不见注释问题

    1.项目属性---->生成----->勾选XML文档文件: 2.使用的时候该文件和dll放在一块.

  3. Alpha 冲刺报告(3/10)

    Alpha 冲刺报告 队名:洛基小队 峻雄(组长) 已完成:开始编写角色的移动脚本 明日计划:继续学习并进行脚本编写 剩余任务:物品背包交互代码 困难:如何把各个模块的脚本整合起来 --------- ...

  4. Thinkphp5的ajax接口实现

    前一篇讲到thinkphp5从数据库获取数据之后赋给视图view,前一篇从数据渲染方式来说是服务端数据渲染,这一章则是浏览器端数据渲染.按照知识总结依据来划分,这是两种不同的技术场景. 下面介绍具体的 ...

  5. nginx的平滑升级,不间断服务

    nginx的平滑升级,不间断服务   Nginx更新真的很快,最近nginx的1.0.5稳定版,nginx的0.8.55和nginx的0.7.69旧的稳定版本已经发布.我一项比较喜欢使用新版本的软件, ...

  6. Android------去除标题栏

    这里暂时只给出一种方法,在java代码中去除 1.继承Activity 在onCreate方法中 getWindow().setFlags(WindowManager.LayoutParams.FLA ...

  7. byte字节的输入流 建议使用字节数组形式接受内容 因为当输入流是汉字时候 会超出字节的范围 出现无法读取的现象

    byte字节的输入流 建议使用字节数组形式接受内容 因为当输入流是汉字时候 会超出字节的范围 出现无法读取的现象

  8. Xcode开发技巧之code snippets(代码片段)

    一.什么是代码片段 当在Xcode中输入dowhile并回车后,Xcode会出现下图所示的提示代码: 这就是代码片段,目的是使程序员以最快的速度输入常用的代码片段,提高编程效率.该功能是从Xcode4 ...

  9. poj 1719 Shooting Contest (二分匹配)

    Shooting Contest Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3812   Accepted: 1389 ...

  10. 用select (多路复用)模拟一个 socket server

    需求:用select (多路复用)模拟一个 socket server.可以接收多并发. 1. 一开始是检测自己,如果我有活动了,就说明有客户端要连我了. #用select去模拟socket,实现单线 ...