UVA_11922 Permutation Transformer 【splay树】
一、题目
UVA11922
二、分析
为什么会有伸展树?
伸展树与AVL的区别除了保持平衡的方式不同外,最重要的是在每次查找点时,让该点旋转到根结点,这里可以结合计算机里的局部性原理思考。
伸展树有什么优势?
有了伸展树,我们可以根据每次到根节点的值,根据二叉搜索树的性质,可以将整棵树划分成两个部分,左子树的值都比根结点值大,右子树的值都比根结点小。
该题除了伸展树还用到了什么?
该题还需要旋转,所以,需要像线段树的lazy标记一样标记是否需要旋转。
有什么需要注意的地方?
一定注意写法的不同,构建树的范围不同,如果没有定于null数组,则需要将建树范围从$[1,n]$扩为$[0,n]$,因为空指针的sum(表示以该结点为根的树的大小)是不清楚的。
三、AC代码
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 struct Node 8 { 9 Node *ch[2]; 10 int sum, val; 11 int flip; 12 Node(int v = 0) 13 { 14 val = v; 15 sum = 1; 16 flip = 0; 17 ch[0] = ch[1] = NULL; 18 } 19 int cmp(int x) 20 { 21 int d = x - (ch[0] == NULL ? 0 : ch[0]->sum); 22 if(d == 1) return -1; 23 else return d <= 0 ? 0 : 1; 24 } 25 void maintain() 26 { 27 sum = 1; 28 if(ch[0] != NULL) sum += ch[0]->sum; 29 if(ch[1] != NULL) sum += ch[1]->sum; 30 } 31 void pushdown() 32 { 33 if(flip) 34 { 35 flip = 0; 36 swap(ch[0], ch[1]); //** 37 if(ch[0] != NULL) 38 ch[0]->flip = !ch[0]->flip; 39 if(ch[1] != NULL) 40 ch[1]->flip = !ch[1]->flip; 41 } 42 } 43 }; 44 45 void build(Node* &o, int l, int r) 46 { 47 if(l > r) 48 return; 49 int mid = (l + r) >> 1; 50 o = new Node(mid); 51 build(o->ch[0], l, mid - 1); 52 build(o->ch[1], mid + 1, r); 53 o->maintain(); 54 } 55 56 void rotate(Node* &o, int d) 57 { 58 Node *k = o->ch[d^1]; 59 o->ch[d^1] = k->ch[d]; 60 k->ch[d] = o; 61 o->maintain(); 62 k->maintain(); 63 o = k; 64 } 65 66 67 void splay(Node* &o, int k) 68 { 69 o->pushdown(); 70 int d = o->cmp(k); 71 if(d == 1) 72 k -= (o->ch[0] == NULL ? 0 : o->ch[0]->sum) + 1; 73 //当前结点不是第k个,则需要往上伸展 74 if(d != -1) 75 { 76 Node *p = o->ch[d]; 77 p->pushdown(); 78 79 int d2 = p->cmp(k); 80 int k2 = (d2 == 0 ? k : k - (p->ch[0] == NULL ? 0 :p->ch[0]->sum) - 1); 81 if(d2 != -1) 82 { 83 splay(p->ch[d2], k2); 84 //x,x的父节点,x祖父结点三点共线 85 if(d == d2) rotate(o, d^1); 86 //不共线 87 else rotate(o->ch[d], d); 88 } 89 rotate(o, d^1); 90 } 91 } 92 93 94 void print(Node* &o) //一定要传引用 95 { 96 o->pushdown(); 97 if(o->ch[0] != NULL) print(o->ch[0]); 98 if(o->val) 99 printf("%d\n", o->val); 100 if(o->ch[1] != NULL) print(o->ch[1]); 101 102 delete o; 103 o = NULL; 104 } 105 106 Node* merge(Node* left, Node* right) 107 { 108 //left不能为NULL 109 //因为初始化了sum为1,对于空指针的sum,不清楚大小 110 //如何避免:建树从0开始,即保证sum>0 111 splay(left, left->sum); 112 left->ch[1] = right; 113 left->maintain(); 114 return left; 115 } 116 117 118 void split(Node *o, int k, Node* &left, Node* &right) 119 { 120 splay(o, k); 121 left = o; 122 right = o->ch[1]; 123 o->ch[1] = NULL; 124 left->maintain(); 125 } 126 127 128 int main() 129 { 130 //freopen("input.txt", "r", stdin); 131 //freopen("out.txt", "w", stdout); 132 int N, M, a, b; 133 while(scanf("%d %d", &N, &M)==2) 134 { 135 Node *root = NULL; 136 Node *left, *mid, *right, *o; 137 //上述模板注意不能用空指针 138 //必须从0开始,不然会RE 139 build(root, 0, N); 140 141 for(int i = 0; i < M; i++) 142 { 143 scanf("%d %d", &a, &b); 144 //树里面有0所以是a 145 split(root, a, left, o); 146 split(o, b - a + 1, mid, right); 147 mid->flip ^= 1; 148 root = merge(merge(left, right), mid); 149 } 150 print(root); 151 } 152 return 0; 153 }
转载于:https://www.cnblogs.com/dybala21/p/10725777.html
UVA_11922 Permutation Transformer 【splay树】相关推荐
- AVL树、splay树(伸展树)和红黑树比较
AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...
- poj 3468 Splay 树
大二上的时候.写过一个AVL的操作演示,今天一看Splay.发现和AVL事实上一样,加上线段树的基础,懒惰标记什么都知道.学起来轻松很多哦 我參考的模板来自这里 http://blog.csdn.n ...
- [Splay伸展树]splay树入门级教程
首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...
- 平衡树【Splay树】学习小记
简介 平衡树,顾名思义,平衡的搜索二叉树. 常见的平衡树都能将树的深度保持在 lg n \lg_n lgn 的级别内,防止退化成链. 一些平衡树可以通过旋转.分裂.合并等操作完成更加高级的.二叉 ...
- 8.1 Splay树
参考博客: https://blog.csdn.net/hellochenlu/article/details/53022709 参考博客: https://blog.csdn.net/amoscyk ...
- HNOI 2002 营业额统计(Splay树)
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 6923 Solved: 2286 [Submit][St ...
- bzoj2733 永无乡 splay树的启发式合并
https://vjudge.net/problem/HYSBZ-2733 给一些带权点,有些点是互相连通的, 然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号 并查集 ...
- Splay树各操作--数组
伸展树删除元素非常方便.. View Code #include <stdio.h>#include <string.h>#include <algorithm># ...
- 线段树 ---- CF452F. Permutation(线段树维护序列Hash)
题目链接 题目大意: 就是给你一个全排列,问你是否存在一个c=a+b2c=\frac{a+b}{2}c=2a+b 满足ccc的位置在a,ba,ba,b之间 解题思路: 首先我们先按顺序遍历,我们假设 ...
最新文章
- java和打印机_java实现打印机打印的区别
- RestFramework之认证组件
- python生成验证码_python之验证码生成(gvcode与captcha)
- python opencv 教程_OpenCV-Python系列教程介绍
- log4j slf4j实现_日志那点事儿——slf4j源码剖析
- 上海亚商投顾:沪指缩量跌0.43%
- 牡丹江java奔腾有知道的吗_老转盘道和“奔腾广场”之间,藏着多少个日新月异?...
- [R语言] 生成随机数
- Google Open Images Dataset V4
- 傻白入门芯片设计,三大基本定律(十)
- 美赛论文Latex简易模板 | 快速上手(附注释)
- 数字货币期货现货交易技巧,把握关键进场的买入点!(纯干货)
- 博弈论与SG函数(Nim游戏)
- 不想打工在家创业这个生意让你月入过万
- 在html里面加入flash,如何在HTML页面插入flash代码
- # 解决微信小程序遮罩层底部页面滚动
- CRM系统,覆盖企业多应用场景
- rabbitmq报错:Listener method could not be invoked with the incoming message
- 币圈投资者 慎入“代投”陷阱!
- 低学历计算机工作,非常适合低学历考生学习的5大技术,就业容易且高薪,可安身立命...
热门文章
- Django 的模板语法之过滤器
- mysql查看死锁和解除锁
- Java图片,视频上传,截取视频帧以及文件下载和视频IO获取
- Android应用开发基础篇(12)-----Socket通信(转载)
- 遭遇“HTTP 错误 500.19 无法访问请求的页面,因为该页的相关配置数据无效。”...
- OpenCV环境下Laplace(拉普拉斯)和Roberts基本边缘检测算子的实现代码
- android ndk mac安装成功,Mac下Android Studio NDK 环境搭建并运行
- mysql show语句_mysql常用show语句
- git工具tig用法
- leetcode算法题--二叉搜索树的后序遍历序列