一、题目

UVA11922

二、分析

为什么会有伸展树?

伸展树与AVL的区别除了保持平衡的方式不同外,最重要的是在每次查找点时,让该点旋转到根结点,这里可以结合计算机里的局部性原理思考。

伸展树有什么优势?

有了伸展树,我们可以根据每次到根节点的值,根据二叉搜索树的性质,可以将整棵树划分成两个部分,左子树的值都比根结点值大,右子树的值都比根结点小。

该题除了伸展树还用到了什么?

该题还需要旋转,所以,需要像线段树的lazy标记一样标记是否需要旋转。

有什么需要注意的地方?

一定注意写法的不同,构建树的范围不同,如果没有定于null数组,则需要将建树范围从$[1,n]$扩为$[0,n]$,因为空指针的sum(表示以该结点为根的树的大小)是不清楚的。

三、AC代码

 #include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; struct Node
{
Node *ch[];
int sum, val;
int flip;
Node(int v = )
{
val = v;
sum = ;
flip = ;
ch[] = ch[] = NULL;
}
int cmp(int x)
{
int d = x - (ch[] == NULL ? : ch[]->sum);
if(d == ) return -;
else return d <= ? : ;
}
void maintain()
{
sum = ;
if(ch[] != NULL) sum += ch[]->sum;
if(ch[] != NULL) sum += ch[]->sum;
}
void pushdown()
{
if(flip)
{
flip = ;
swap(ch[], ch[]); //**
if(ch[] != NULL)
ch[]->flip = !ch[]->flip;
if(ch[] != NULL)
ch[]->flip = !ch[]->flip;
}
}
}; void build(Node* &o, int l, int r)
{
if(l > r)
return;
int mid = (l + r) >> ;
o = new Node(mid);
build(o->ch[], l, mid - );
build(o->ch[], mid + , r);
o->maintain();
} 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;
} void splay(Node* &o, int k)
{
o->pushdown();
int d = o->cmp(k);
if(d == )
k -= (o->ch[] == NULL ? : o->ch[]->sum) + ;
//当前结点不是第k个,则需要往上伸展
if(d != -)
{
Node *p = o->ch[d];
p->pushdown(); int d2 = p->cmp(k);
int k2 = (d2 == ? k : k - (p->ch[] == NULL ? :p->ch[]->sum) - );
if(d2 != -)
{
splay(p->ch[d2], k2);
//x,x的父节点,x祖父结点三点共线
if(d == d2) rotate(o, d^);
//不共线
else rotate(o->ch[d], d);
}
rotate(o, d^);
}
} void print(Node* &o) //一定要传引用
{
o->pushdown();
if(o->ch[] != NULL) print(o->ch[]);
if(o->val)
printf("%d\n", o->val);
if(o->ch[] != NULL) print(o->ch[]); delete o;
o = NULL;
} Node* merge(Node* left, Node* right)
{
//left不能为NULL
//因为初始化了sum为1,对于空指针的sum,不清楚大小
//如何避免:建树从0开始,即保证sum>0
splay(left, left->sum);
left->ch[] = right;
left->maintain();
return left;
} void split(Node *o, int k, Node* &left, Node* &right)
{
splay(o, k);
left = o;
right = o->ch[];
o->ch[] = NULL;
left->maintain();
} int main()
{
//freopen("input.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int N, M, a, b;
while(scanf("%d %d", &N, &M)==)
{
Node *root = NULL;
Node *left, *mid, *right, *o;
//上述模板注意不能用空指针
//必须从0开始,不然会RE
build(root, , N); for(int i = ; i < M; i++)
{
scanf("%d %d", &a, &b);
//树里面有0所以是a
split(root, a, left, o);
split(o, b - a + , mid, right);
mid->flip ^= ;
root = merge(merge(left, right), mid);
}
print(root);
}
return ;
}

UVA_11922 Permutation Transformer 【splay树】的更多相关文章

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

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

  2. UVa 11922 - Permutation Transformer 伸展树

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

  3. UVA - 11922 Permutation Transformer (splay)

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

  4. Splay树-Codevs 1296 营业额统计

    Codevs 1296 营业额统计 题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司 ...

  5. ZOJ3765 Lights Splay树

    非常裸的一棵Splay树,需要询问的是区间gcd,但是区间上每个数分成了两种状态,做的时候分别存在val[2]的数组里就好.区间gcd的时候基本上不支持区间的操作了吧..不然你一个区间里加一个数gcd ...

  6. Splay树再学习

    队友最近可能在学Splay,然后让我敲下HDU1754的题,其实是很裸的一个线段树,不过用下Splay也无妨,他说他双旋超时,单旋过了,所以我就敲来看下.但是之前写的那个Splay越发的觉得不能看,所 ...

  7. 暑假学习日记:Splay树

    从昨天开始我就想学这个伸展树了,今天花了一个上午2个多小时加下午2个多小时,学习了一下伸展树(Splay树),学习的时候主要是看别人博客啦~发现下面这个博客挺不错的http://zakir.is-pr ...

  8. 1439. Battle with You-Know-Who(splay树)

    1439 路漫漫其修远兮~ 手抄一枚splay树 长长的模版.. 关于spaly树的讲解   网上很多随手贴一篇 貌似这题可以用什么bst啦 堆啦 平衡树啦 等等 这些本质都是有共同点的 查找.删除特 ...

  9. 伸展树(Splay树)的简要操作

    伸展树(splay树),是二叉排序树的一种.[两个月之前写过,今天突然想写个博客...] 伸展树和一般的二叉排序树不同的是,在每次执行完插入.查询.删除等操作后,都会自动平衡这棵树.(说是自动,也就是 ...

随机推荐

  1. 解决 Windows 系统使用 Homestead 运行 Laravel 本地项目响应缓慢问题

    laravel-china.com: https://laravel-china.org/articles/9009/solve-the-slow-response-problem-of-window ...

  2. 让Ubuntu使用阿里云国内源,解决下载速度慢问题。

    阿里云镜像官方地址 http://mirrors.aliyun.com/ 找到最新源地址列表: http://www.linuxdiyf.com/linux/23163.html 软件包管理中心(推荐 ...

  3. UVaLive 3126 Taxi Cab Scheme (最小路径覆盖)

    题意:有 n 个客人,要从 si 到 ti,每个人有一个出发时间,现在让你安排最少和出租车去接,在接客人时至少要提前一分钟到达客人的出发地点. 析:把每个客人看成一个结点,然后如果用同一个出租车接的话 ...

  4. awk基础04-内置函数

        在awk中常用的内置函数大概分为:数值函数.字符函数.时间函数.二进制操作函数.数组函数.自定义函数等. 数值函数   常用的数值函数主要有int.rand.srand.sqrt等.详细如下所 ...

  5. [label][转载][JavaSript]querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?

     轉載出處: http://www.zhihu.com/question/24702250 querySelectorAll 相比下面这些方法有什么区别? getElementsByTagName g ...

  6. 常用脚本--查看死锁和阻塞usp_who_lock

    USE [master] GO /****** Object: StoredProcedure [dbo].[sp_who_lock] Script Date: 02/07/2014 11:51:24 ...

  7. 基于Quartz.net的远程任务管理系统 三

    在上一篇中,已经把服务端都做好了.那接下来就是Web的管理端了,因为很多时候服务器是有专门的运维来管理的,我们没有权限去操作,所以有个可以管理Job的工具还是很有必要的. Web管理端,我选择现在很成 ...

  8. Oracle数据泵导出导入(expdp/impdp)

    一.创建表空间 create tablespace atp logging datafile 'D:\oracle\oradata\orcl\atp.dbf' size 50m autoextend ...

  9. ASP Session的功能的缺陷(进程外的Session)

    目前ASP的开发人员都正在使用Session这一强大的功能,但是在他们使用的过程中却发现了ASP Session有以下缺陷: 进程依赖性:ASP Session状态存于IIS的进程中,也就是ineti ...

  10. WPF定时刷新UI界面

    代码: using NHibernate.Criterion; using System; using System.Collections.Generic; using System.Collect ...