一、题目

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树】相关推荐

  1. AVL树、splay树(伸展树)和红黑树比较

    AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...

  2. poj 3468 Splay 树

    大二上的时候.写过一个AVL的操作演示,今天一看Splay.发现和AVL事实上一样,加上线段树的基础,懒惰标记什么都知道.学起来轻松很多哦 我參考的模板来自这里  http://blog.csdn.n ...

  3. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  4. 平衡树【Splay树】学习小记

    简介 平衡树,顾名思义,平衡的搜索二叉树. 常见的平衡树都能将树的深度保持在 lg ⁡ n \lg_n lgn​ 的级别内,防止退化成链. 一些平衡树可以通过旋转.分裂.合并等操作完成更加高级的.二叉 ...

  5. 8.1 Splay树

    参考博客: https://blog.csdn.net/hellochenlu/article/details/53022709 参考博客: https://blog.csdn.net/amoscyk ...

  6. HNOI 2002 营业额统计(Splay树)

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 6923  Solved: 2286 [Submit][St ...

  7. bzoj2733 永无乡 splay树的启发式合并

    https://vjudge.net/problem/HYSBZ-2733 给一些带权点,有些点是互相连通的, 然后给出2种操作,在两点间加一条边,或者询问一个点所在的连通块内的第k小值的编号 并查集 ...

  8. Splay树各操作--数组

    伸展树删除元素非常方便.. View Code #include <stdio.h>#include <string.h>#include <algorithm># ...

  9. 线段树 ---- CF452F. Permutation(线段树维护序列Hash)

    题目链接 题目大意: 就是给你一个全排列,问你是否存在一个c=a+b2c=\frac{a+b}{2}c=2a+b​ 满足ccc的位置在a,ba,ba,b之间 解题思路: 首先我们先按顺序遍历,我们假设 ...

最新文章

  1. java和打印机_java实现打印机打印的区别
  2. RestFramework之认证组件
  3. python生成验证码_python之验证码生成(gvcode与captcha)
  4. python opencv 教程_OpenCV-Python系列教程介绍
  5. log4j slf4j实现_日志那点事儿——slf4j源码剖析
  6. 上海亚商投顾:沪指缩量跌0.43%
  7. 牡丹江java奔腾有知道的吗_老转盘道和“奔腾广场”之间,藏着多少个日新月异?...
  8. [R语言] 生成随机数
  9. Google Open Images Dataset V4
  10. 傻白入门芯片设计,三大基本定律(十)
  11. 美赛论文Latex简易模板 | 快速上手(附注释)
  12. 数字货币期货现货交易技巧,把握关键进场的买入点!(纯干货)
  13. 博弈论与SG函数(Nim游戏)
  14. 不想打工在家创业这个生意让你月入过万
  15. 在html里面加入flash,如何在HTML页面插入flash代码
  16. # 解决微信小程序遮罩层底部页面滚动
  17. CRM系统,覆盖企业多应用场景
  18. rabbitmq报错:Listener method could not be invoked with the incoming message
  19. 币圈投资者 慎入“代投”陷阱!
  20. 低学历计算机工作,非常适合低学历考生学习的5大技术,就业容易且高薪,可安身立命...

热门文章

  1. Django 的模板语法之过滤器
  2. mysql查看死锁和解除锁
  3. Java图片,视频上传,截取视频帧以及文件下载和视频IO获取
  4. Android应用开发基础篇(12)-----Socket通信(转载)
  5. 遭遇“HTTP 错误 500.19 无法访问请求的页面,因为该页的相关配置数据无效。”...
  6. OpenCV环境下Laplace(拉普拉斯)和Roberts基本边缘检测算子的实现代码
  7. android ndk mac安装成功,Mac下Android Studio NDK 环境搭建并运行
  8. mysql show语句_mysql常用show语句
  9. git工具tig用法
  10. leetcode算法题--二叉搜索树的后序遍历序列