Splay(伸展树)实现可分裂与合并的序列

对于BST,除了Treap树之外,还有一种Splay的伸展树,他能快速的分裂与合并。

重要的操作是伸展操作,将一个指定的结点 x 旋转到根的过程。

分三种情况,一次单旋,两次同向单旋,两次反向旋转。可以手动模拟一下这个过程。

到这里,问题常常是将序列的第 k 个元素旋转到根。

首先,要知道的是伸展树里面v存的是什么,是节点的编号(下标)。这样才能像 Treap实现名次树那样,很方便的找到左边第 k 个元素。

//将序列左数第k个元素选择到根
void splay(Node* &o,int k) {
  o->pushdown();
  int d = o->cmp(k);
  if(d==1) k-=o->ch[0]->s + 1;
  if(d!=-1) {
      Node* p = o->ch[d];

      p->pushdown();
      int d2 = p->cmp(k);
      int k2 = (d2==0 ? k : k - p->ch[0]->s - 1);
      if(d2!=-1) {
          splay(p->ch[d2],k2);
          if(d==d2) rotate(o,d^1);
          else rotate(o->ch[d],d);
      }
      rotate(o,d^1);
  }
}

分裂与合并:

分裂:从序列从左第 k 个元素分裂,就是将序列的 o 的第 K 小元素伸展到根,断开树根与右子节点。

合并:将left部分最大的元素旋转到根,将right作为 left的右子树。(保证right>left所有元素)。

// 合并操作。假定left所有元素小于 right
Node* merge(Node* left,Node* right) {
  splay(left,left->s);
  left->ch[1] = right;
  left->maintain();
  return left;
}

//把 o 前 k 个小结点放到left里面,其他放到ritht里面,如果不够right = null
void split(Node* o,int k,Node* &left,Node* &right) {
  splay(o,k);
  left = o;
  right = o->ch[1];
  o->ch[1] = null;
  left->maintain();
}

有时,对于序列有反转操作,这时,利用 线段树的 lazy标记,标记某一段是否反转。

对于,数据结构的定义:用一个Node数组,和一个Node 的 root指针,指向这个数组的元素。

#include <bits/stdc++.h>

using namespace std;

struct Node {
Node *ch[];
int s;
int flip;
int v;
int cmp(int k) const {
int d = k - ch[]->s;
if(d==) return -; //序列第 k 个找到
return d <= ? : ;
} void maintain() {
s = ch[]->s + ch[]->s + ;
} void pushdown() {
if(flip) {
flip = ;
swap(ch[],ch[]);
ch[]->flip = !ch[]->flip;
ch[]->flip = !ch[]->flip;
}
}
}; Node *null = new Node(); // d = 0 左旋
void rotate(Node* &o,int d) {
Node* k = o->ch[d^];
o->ch[d^] = k->ch[d];
k->ch[d] = o;
o->maintain();
k->maintain();
o = k;
} //将序列左数第k个元素选择到根
void splay(Node* &o,int k) {
o->pushdown();
int d = o->cmp(k);
if(d==) k-=o->ch[]->s + ;
if(d!=-) {
Node* p = o->ch[d]; p->pushdown();
int d2 = p->cmp(k);
int k2 = (d2== ? k : k - p->ch[]->s - );
if(d2!=-) {
splay(p->ch[d2],k2);
if(d==d2) rotate(o,d^);
else rotate(o->ch[d],d);
}
rotate(o,d^);
}
} // 合并操作。假定left所有元素小于 right
Node* merge(Node* left,Node* right) {
splay(left,left->s);
left->ch[] = right;
left->maintain();
return left;
} //把 o 前 k 个小结点放到left里面,其他放到ritht里面,如果不够right = null
void split(Node* o,int k,Node* &left,Node* &right) {
splay(o,k);
left = o;
right = o->ch[];
o->ch[] = null;
left->maintain();
} const int maxn = 1e5+;
struct SplaySequence {
int n;
Node seq[maxn];
Node *root; Node* build(int sz) {
if(!sz) return null;
Node* L = build(sz/);
Node* o = &seq[++n];
o->v = n;
o->ch[] = L;
o->ch[] = build(sz-sz/-);
o->flip = o ->s = ;
o->maintain();
return o;
} void init(int sz) {
n = ;
null->s = ;
root = build(sz);
for(int i = ; i < sz; i++)
printf("%d ",seq[i].v);
puts("");
} }; vector<int> ans;
void print(Node* o) {
if(o!=null) {
o->pushdown();
print(o->ch[]);
ans.push_back(o->v);
print(o->ch[]);
}
} void debug(Node* o) {
if(o!=null) {
o->pushdown();
debug(o->ch[]);
printf("%d \n",o->v -);
debug(o->ch[]);
}
} SplaySequence ss; int main()
{
int n,m;
scanf("%d%d",&n,&m);
ss.init(n+); debug(ss.root); for(int i = ; i < m; i++) {
int a,b;
scanf("%d%d",&a,&b);
Node* left,*mid,*right,*o;
split(ss.root,a,left,o);
split(o,b-a+,mid,right);
mid->flip ^=;
ss.root = merge(merge(left,right),mid);
} print(ss.root);
for(int i = ; i < (int)ans.size(); i++)
printf("%d\n",ans[i]-); return ;
}

Uva 11922 Splay的更多相关文章

  1. UVA 11922 Splay tree

    UVA 11922 题意: 有n个数1~n 操作a,b表示取出第a~b个数,翻转后添加到数列的尾部 输入n,m 输入m条指令a,b 输出最终的序列 代码: #include<iostream&g ...

  2. UVa 11922 & splay的合并与分裂

    题意: 1个1—n的排列,实现一下操作:将a—b翻转并移动至序列的最后. SOL: splay维护区间的裸题——不过平衡树的题目貌似都是裸的吧...就是看操作的复杂程度罢... 如何取区间呢,我们在s ...

  3. uva 11922 Permutation Transforme/splay tree

    原题链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 伸展树的区间翻转剪切... 如下: #include< ...

  4. UVA 11922 Permutation Transformer(Splay Tree)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18902 [思路] 伸展树+打标记. 用伸展树维护这个序列,使得能 ...

  5. UVA - 11922 Permutation Transformer (splay)

    题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...

  6. UVA 11922 Permutation Transformer (Splay树)

    题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...

  7. UVA 11922 Permutation Transformer —— splay伸展树

    题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...

  8. UVA 11922 伸展树Splay 第一题

    上次ZOJ月赛碰到一个题目要求对序列中的某个区间求gcd,并且还要随时对某位数字进行修改 插入 删除,当时马上联想到线段树,但是线段树不支持增删,明显还是不可以的,然后就敲了个链表想暴力一下,结果TL ...

  9. UVa 11922 - Permutation Transformer 伸展树

    第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...

随机推荐

  1. js 中的! 和 !! 的区别

    Js中!的用法是比较灵活的,它除了做逻辑运算常常会用!做类型判断,可以用!与上对象来求得一个布尔值,1.!可将变量转换成boolean类型,null.undefined和空字符串取反都为false,其 ...

  2. (转)Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解

    原文:http://blog.51cto.com/freeloda/1288553 大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负载均衡 六.Ng ...

  3. BFC --- Block Formatting Context --- 块级格式化上下文

    虽然知道块级格式化上下文是什么东西,但要我把这个东西给说清楚,还真的不是一件容易的事儿,所以这篇文章我就要说说清楚到底什么使传说中的BFC,即块级格式化上下文. 一.BFC的通俗理解 通俗的理解 -- ...

  4. 02-使用注解配置spring

    1 准备工作 1.导包 4+2+spring-aop[新版本需要导入 spring-aop 包] 2.为主配置文件引入新的命名空间(约束) [context] 3.开启使用注解代理配置文件 4.在类中 ...

  5. 读书笔记-NIO的工作方式

    读书笔记-NIO的工作方式 1.BIO是阻塞IO,一旦阻塞线程将失去对CPU的使用权,当前的网络IO有一些解决办法:1)一个客户端对应一个处理线程:2)采用线程池.但也会出问题. 2.NIO的关键类C ...

  6. this,super,和继承

    this是指当前对象的引用,super是指直接父类的引用 比如 我建造一个类 public class Person(){ private String name; private  int age; ...

  7. AtCoder Grand Contest 023 F - 01 on Tree

    Description 题面 Solution HNOI-day2-t2 复制上去,删点东西,即可 \(AC\) #include<bits/stdc++.h> using namespa ...

  8. /Date(1410019200000+0800)/如何转换为date对象

    <script type="text/javascript">var s = '/Date(1410019200000+0800)/ '; s.replace(/Dat ...

  9. 利用ajax短轮询+php与服务器交互制作简易即时聊天网站

    主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Server-sent Events). 本文主要介绍ajax短轮询的简易实现方式. 看懂此文 ...

  10. mysql 语句学习一 关于系统信息的查询

    首先说一下,SQL语句是不区分大小写的. 1.SELECT VERSION();           -- 查询当前版本号 2.SELECT CURRENT_TIME(); -- 查询当前时间 3.S ...