Splay

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
struct node *nil;//防止真的访问了NULL导致re(从零开始的编码生活)
struct node
{
int val;//节点值
int size;//以他为根的节点的子树节点个数(包括他自己)
int flag;//懒标记
node *ch[2];//左右儿子
void sum()//重新计算size
{
size=1+ch[0]->size+ch[1]->size;//因为这里我们定义了不会re的无意义空地址。所以就不用判断
}
int cmp(int kth)//比较该往那颗子树上走
{
int s=ch[0]->size;
if(kth==s+1)//就是当前根
return -1;
return (kth <= s ? 0 : 1);
}
}*root;
int n,m;
void init()//初始化
{
nil=new node;
nil->flag=0;
nil->size=0;
nil->val=0;
nil->ch[0]=nil->ch[1]=nil;
root=nil;
}
node *New()//申请内存并初始化
{
node *res=new node;
res->size=1;
res->flag=0;
res->ch[0]=res->ch[1]=nil;
return res;
}
void rotato(node* &now,int base)//旋转函数。应为这里是引用指针。所以直接指向就可以了。不用顾忌其他东西辣( ̄▽ ̄)~*
{
node *k=now->ch[base^1];//利用异或进行取反
now->ch[base^1]=k->ch[base];
k->ch[base]=now;
now->sum();//先计算被旋转下去的根,再计算新的根
k->sum();
now=k;
}
void build(node* &now,int l,int r)//建树,一定要引用。l为左边界。
{
if(l>r)
return ;
int mid=(l+r)>>1;
if(now==nil)//如果为空就动态申请,当然也可以动态删除
{
now=New();
now->val=mid;
}
build(now->ch[0],l,mid-1);//左右递归的建树
build(now->ch[1],mid+1,r);
now->sum();
return ;
}
void push_down(node* &now)//下放lazy tag
{
if(now!=nil&&now->flag)
{
swap(now->ch[0],now->ch[1]);
now->ch[0]->flag^=1;
now->ch[1]->flag^=1;
now->flag=0;
}
return ;
}
void visit(node* &now)//中序便利
{
if(now==nil)
return ;
push_down(now);
visit(now->ch[0]);
if(now->val!=0&&now->val!=n+1)
printf("%d ",now->val);
visit(now->ch[1]);
}
void splaykth(node* &now,int kth)//将以now为根的树中把第kth小的旋转到根上
{
push_down(now);
int d=now->cmp(kth);
if(d!=-1)
{
push_down(now->ch[d]);
if(d==1)
kth-=now->ch[0]->size+1;//换根要重新计算kth,下同
int d2=now->ch[d]->cmp(kth);
if(d2!=-1)
{
if(d2==1)
kth-=now->ch[d]->ch[0]->size+1;
splaykth(now->ch[d]->ch[d2],kth);
if(d==d2)
rotato(now,d2^1),rotato(now,d^1);//一字型
else
rotato(now->ch[d],d2^1),rotato(now,d^1);//之字形
}
else
rotato(now,d^1);//单旋
}
}//其实这里应该要判空的,以防止非法情况出现。不过根据这个题。我们调用的时候没有非法情况
void Reverse(int l,int r)//翻转,这里因为有可能涉及到将1~n都翻转一遍。所以我们可以建两个哨兵节点,位置在0,n+1上。
{ //将l~r翻转
//l,r为第l个数到第r个数(1~n中)
splaykth(root,l);//把l-1翻上来
splaykth(root->ch[1],r+1-root->ch[0]->size);//把r+1翻到右子树根的位置上。这样根节点右儿子的左子树上就是l~r。
root->ch[1]->ch[0]->flag^=1;//打上懒标记
return ;
}
int main()
{
init();
scanf("%d%d",&n,&m);
build(root,0,n+1);
int a,b;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
Reverse(a,b);
}
/*splaykth(root,7);
cout<<root->val;*/
visit(root);//中序遍历一波
}

P3391 【模板】文艺平衡树(Splay)的更多相关文章

  1. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  2. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  3. 【洛谷P3391】文艺平衡树——Splay学习笔记(二)

    题目链接 Splay基础操作 \(Splay\)上的区间翻转 首先,这里的\(Splay\)维护的是一个序列的顺序,每个结点即为序列中的一个数,序列的顺序即为\(Splay\)的中序遍历 那么如何实现 ...

  4. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  5. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  6. BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6881  Solved: 4213[Submit][Sta ...

  7. BZOJ3223 文艺平衡树(splay)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  8. BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Sta ...

  9. Tyvj P1729 文艺平衡树 Splay

    题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 ...

  10. BZOJ 3223: Tyvj 1729 文艺平衡树(splay)

    速度居然进前十了...第八... splay, 区间翻转,用一个类似线段树的lazy标记表示是否翻转 ------------------------------------------------- ...

随机推荐

  1. 转 python 的常用函数replace, split(),enumerate() 函数

    1.execmd = "su - " + ou + " -c 'sqlplus / as sysdba << EOF\n " + execmd3 + ...

  2. VC6.0开发中一些链接错误的解决方法

    (1)error LNK2001: unresolved external symbol _main 编号:LNK2001 直译:未解决的外部符号:_main. 错误分析:缺少main函数.看看mai ...

  3. B-树 B+树 红黑树

    B树是一种多路平衡查找树,它的每一个节点最多包含k个孩子,k被称为B树的阶.k的大小取决于磁盘页的大小.B树主要应用于文件系统以及部分数据库索引,比如著名的非关系型数据库MongoDB.一个m阶的B树 ...

  4. MQTT学习之一

    一MQTT特性: 基于C/S,发布订阅(发布者服务器->云平台代理->订阅客户端)一对多结构,适用于低带宽高延时,基于TCP/IP之上.

  5. netbeans 窗体字体大小设置

    当计算机分辨率变大的时候,打开netbeans的时候,字体就会变得越来越小 看起来很不爽,所要就要改变一下,窗体字体大小. 在网上找到了一段修改netbeans窗体字体大小的配置信息,现标记起来,以便 ...

  6. Day3监督学习——决策树原理

    Day3 机器学习监督学习——决策树原理 一.决策树的原理 1.机器学习中分类和预测算法的评估: 准确率 速度 强壮型:有数据缺失或错误时算法的运行 可规模性:数量级规模比较大 可解释性 2.决策树( ...

  7. ubuntu下安装录屏软件

    sudo add-apt-repository ppa:maarten-baert/simplescreenrecorder sudo apt-get update sudo apt-get inst ...

  8. IA-32e架构下的内核初始化内存管理

    初级内存管理单元 关于内存的分页 以往的物理页是按照4KB进行分配和管理的, 而在Linux之后流行的就是2MB大小的物理页的分配和管理, 整个物理内存管理单元也是2MB物理页管理的 先获取基本的物理 ...

  9. join() 和 sleep() 区别

    来源于<Java多线程编程核心技术> 一.join() 作用 在很多情况,主线程创建并启动子线程,如果子线程中需要进行大量的耗时计算,主线程往往早于子线程结束.这时,如果主线程想等待子线程 ...

  10. C#中正则表达式的构建与匹配

    使用方法 [1]用用命名空间System.Text.RegularExpressions [2]构造正则表达式 在使用正则表达式时,要先构造正则表达式,这就用到了Regex类,其构建方式有两种: 基本 ...