Uva 11922 Splay
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[2];int s;int flip;int v;int cmp(int k) const {int d = k - ch[0]->s;if(d==1) return -1; //序列第 k 个找到return d <=0 ? 0 : 1;}void maintain() {s = ch[0]->s + ch[1]->s + 1;}void pushdown() {if(flip) {flip = 0;swap(ch[0],ch[1]);ch[0]->flip = !ch[0]->flip;ch[1]->flip = !ch[1]->flip;}} };Node *null = new Node();// d = 0 左旋 void rotate(Node* &o,int d) {Node* k = o->ch[d^1];o->ch[d^1] = 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==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);} }// 合并操作。假定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(); }const int maxn = 1e5+10; struct SplaySequence {int n;Node seq[maxn];Node *root;Node* build(int sz) {if(!sz) return null;Node* L = build(sz/2);Node* o = &seq[++n];o->v = n;o->ch[0] = L;o->ch[1] = build(sz-sz/2-1);o->flip = o ->s = 0;o->maintain();return o;}void init(int sz) {n = 0;null->s = 0;root = build(sz);for(int i = 0; i < sz; i++)printf("%d ",seq[i].v);puts("");}};vector<int> ans; void print(Node* o) {if(o!=null) {o->pushdown();print(o->ch[0]);ans.push_back(o->v);print(o->ch[1]);} }void debug(Node* o) {if(o!=null) {o->pushdown();debug(o->ch[0]);printf("%d \n",o->v -1);debug(o->ch[1]);} }SplaySequence ss;int main() {int n,m;scanf("%d%d",&n,&m);ss.init(n+1);debug(ss.root);for(int i = 0; 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+1,mid,right);mid->flip ^=1;ss.root = merge(merge(left,right),mid);}print(ss.root);for(int i = 1; i < (int)ans.size(); i++)printf("%d\n",ans[i]-1);return 0; }
转载于:https://www.cnblogs.com/TreeDream/p/7554716.html
Uva 11922 Splay相关推荐
- oracle备份数据表叫什么,oracle备份表和数据
oracle 备份数据 如果备份表存在 原表t_base_employee,备份表t_base_employee20180718 insert into t_base_employee0718 sel ...
- 二逼平衡树——树套树(线段树套Splay平衡树)
题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...
- [搜索]UVa 129 困难的串
题意:将一个包含两个相邻的重复子串的子串,称为"容易的串",其他为"困难的串". 输入正整数n和l,输出由前l个字符组成的,字典序第n小的困难的串. 输入样例: ...
- 简析平衡树(三)——浅谈Splay
前言 原本以为\(Treap\)已经很难了,学习了\(Splay\),我才知道,没有最难,只有更难.(强烈建议先去学一学\(Treap\)再来看这篇博客) 简介 \(Splay\)是平衡树中的一种,除 ...
- AVL树、splay树(伸展树)和红黑树比较
AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...
- uva 401.Palindromes
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- Uva 3767 Dynamic len(set(a[L:R])) 树套树
Dynamic len(set(a[L:R])) Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://uva.onlinejudge.org/in ...
- UVA 11752 超级幂
UVA 11752 超级幂 Z - The Super Powers Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & ...
- UVa 11174 - Stand in a Line
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
最新文章
- nginx之 nginx-1.9.7 编译安装、理论简介
- js中的if与Java中的if_JavaScript if...else 语句
- jquery 封装页面之间获取值
- String 重载 + 原理分析
- mysqli 返回一条结果_php中mysqli 处理查询结果集总结
- delphi socket 怎样把接收到的二进制数据转换成字符串显示_广东qp用户数据免费咨询...
- 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】
- 10深入Redis Cluster
- ul列表中包含input时line-height属性失效的解决办法
- 五大列级庄_酒庄拉菲古堡Chateau Lafite Rothschild, 波尔多五大一级庄之首
- Deep Ordinal Regression Network for Monocular Depth Estimation
- mysql 历史数据迁移,MySQL 历史数据表迁移方法
- 三星s4流量显示无服务器,三星s4有什么隐藏功能
- 7-1 统计大写辅音字母 (15 分)
- mysql导入excel表_mysql怎么导入excel数据?
- 数据结构复习题(一)
- Matlab------如何控制matlab中的数据输出格式
- 如何在Ubuntu 20.04上安装Kvm
- 如何使用windows自带远程桌面连接linux,使用Windows自带远程桌面应用连接CentOS8远程桌面...
- CPL, 门DPL, 描述符DPL 的关系