UVA_11922 Permutation Transformer 【splay树】
一、题目
二、分析
为什么会有伸展树?
伸展树与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树】的更多相关文章
- UVA 11922 Permutation Transformer —— splay伸展树
题意:根据m条指令改变排列1 2 3 4 … n ,每条指令(a, b)表示取出第a~b个元素,反转后添加到排列尾部 分析:用一个可分裂合并的序列来表示整个序列,截取一段可以用两次分裂一次合并实现,粘 ...
- UVa 11922 - Permutation Transformer 伸展树
第一棵伸展树,各种调试模板……TVT 对于 1 n 这种查询我处理的不太好,之前序列前后没有添加冗余节点,一直Runtime Error. 后来加上冗余节点之后又出了别的状况,因为多了 0 和 n+1 ...
- UVA - 11922 Permutation Transformer (splay)
题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...
- Splay树-Codevs 1296 营业额统计
Codevs 1296 营业额统计 题目描述 Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司 ...
- ZOJ3765 Lights Splay树
非常裸的一棵Splay树,需要询问的是区间gcd,但是区间上每个数分成了两种状态,做的时候分别存在val[2]的数组里就好.区间gcd的时候基本上不支持区间的操作了吧..不然你一个区间里加一个数gcd ...
- Splay树再学习
队友最近可能在学Splay,然后让我敲下HDU1754的题,其实是很裸的一个线段树,不过用下Splay也无妨,他说他双旋超时,单旋过了,所以我就敲来看下.但是之前写的那个Splay越发的觉得不能看,所 ...
- 暑假学习日记:Splay树
从昨天开始我就想学这个伸展树了,今天花了一个上午2个多小时加下午2个多小时,学习了一下伸展树(Splay树),学习的时候主要是看别人博客啦~发现下面这个博客挺不错的http://zakir.is-pr ...
- 1439. Battle with You-Know-Who(splay树)
1439 路漫漫其修远兮~ 手抄一枚splay树 长长的模版.. 关于spaly树的讲解 网上很多随手贴一篇 貌似这题可以用什么bst啦 堆啦 平衡树啦 等等 这些本质都是有共同点的 查找.删除特 ...
- 伸展树(Splay树)的简要操作
伸展树(splay树),是二叉排序树的一种.[两个月之前写过,今天突然想写个博客...] 伸展树和一般的二叉排序树不同的是,在每次执行完插入.查询.删除等操作后,都会自动平衡这棵树.(说是自动,也就是 ...
随机推荐
- TOGAF架构培训材料学习总结
作于一个架构师尤其是企业架构师来说,丰富的理论知识可以帮助他在架构规划及管理过程中站在更高的角度去看待问题,历史发展原因有很多已成体系的架构理论,TOGAF是近年来比较接地气的,受到了政府和银 ...
- 看图说话:关于BI那点事儿
[编者按]BI=DW+数据挖掘+业务分析+社会学?BI三部曲:管数据.看数据.源数据.BI有三种放法:技术部.业务部和独立部门.BI的工作=20%数据平台+30%数据支持+50%数据应用.
- HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)
小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...
- UVa 247 Calling Circles (DFS+Floyd)
题意:如果两个人互通电话,那么他们就在一个电话圈里,现在给定 n 个人,并且给定 m 个通话记录,让你输出所有的电话圈. 析:刚开始没想到是Floyd算法,后来才知道是这个算法,利用这个算法进行连通性 ...
- .NET基础 (18)特性
特性1 什么是特性,如何自定义一个特性2 .NET中特性可以在哪些元素上使用3 有哪几种方法可以获知一个元素是否申明某个特性4 一个元素是否可以重复申明同一个特性 特性1 什么是特性,如何自定义一个特 ...
- MySQL数据库Query性能定位
1.SQL前面加 EXPLAIN 定位到sql级别 各个属性的含义 id select查询的序列号 select_type select查询的类型,主要是区别普通查询和联合查询.子查询之类的复杂查询. ...
- Firefox mobile (android) and orientationchange
Firefox for Android does not support the orientationchange event but you can achieve the same result ...
- centos7 安装SSH
1.安装OpenSSH服务(CentOS系统默认安装了openssh) yum install openssh-server -y 2.配置OpenSSH服务(默认的配置已可以正常工作) O ...
- osgi.net框架
osgi.net是一个动态的模块化框架.它向用户提供了模块化与插件化.面向服务构架和模块扩展支持等功能.该平台是OSGi联盟定义的服务平台规范移植到.NET的实现. 简介 尤埃开放服务平台是一个基于. ...
- C#——Winform 无边框随意拖动【转载】
本篇技术内容转载自:http://www.cnblogs.com/ap0606122/archive/2012/10/23/2734964.html using System; using Syste ...