由于数据结构上老师讲了AVL树的rotate,然后去学了一下treap和Splay,这些数据结构还真是神奇啊!

  treap暂时只知道名次树的作用(就是一段动态变化的有序数列,找第K大的元素,用set显然是O(n)的。。)。

  好,正式介绍SplayTree这个神奇的数据结构:暂时的理解是,用于解决一些线段树解决不了的区间问题,比方说区间翻转,区间删除并插入等等(似乎分块也可以解决一些xjbg的区间问题)。。然后,Splay还可以解决掉LCT的问题(暂时还不会,,下次继续学习)。

  然后就愉快地掏出模板吧(直接修改了铭神的模板)。。仓鼠挂的平衡树

  G题,区间翻转+区间切割的。直接掏出模板套上去就是了:

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#define tochange (root->ch[1]->ch[0])
using namespace std;
const int N = + ;
struct node *nill, *root;
struct node {
int val;
int sz;
bool rev;
node *ch[],*fa;
void init(int v = )
{
ch[] = ch[] = fa = nill;
val = v;
sz = ;
}
void up() {
if (this==nill) return ;
sz = ch[]->sz + ch[]->sz + ;
}
void down() {
if (this==nill) return ;
if(rev)
{
rev = false;
ch[]->rev ^= ;
ch[]->rev ^= ;
swap(ch[], ch[]);
}
}
bool d() {
return fa->ch[]==this;
}
void reverse() {
rev ^= ;
std::swap(ch[],ch[]);
}
void setc(node *o,int c) {
ch[c] = o;
o->fa = this;
up();
}
void rot() {
int c = d(),cc = fa->d();
node *z = fa->fa;
node *tmp = fa;
fa->setc(ch[c^],c);
setc(tmp,c^);
if(z!=nill) z->setc(this,cc);
else fa = z; // 这里的if-else不加也行,因为对于nill来说无论儿子是谁都无所谓,
// 并且,setc时的up对nill无效
}
void D() {
if (this==nill) return ;
fa->D();
down();
}
void splay(node *aim = nill) {
D();
while (fa!=aim) {
if (fa->fa!=aim) {
d()==fa->d() ? fa->rot() : rot();
}
rot();
}
if(aim == nill) root = this;
}
}memo[N], *bat; node* findK(node* o, int k)
{
while()
{
o->down();
if(o->ch[]->sz + == k)
{
return o;
}
if(o->ch[]->sz >= k) o = o->ch[];
else
{
k -= o->ch[]->sz + ;
o = o->ch[];
}
}
} node* get_min(node* o)
{
/*while(o->ch[0] != nill)
{
o->down();
o = o->ch[0];
}
return o;*/
// 上面写法错了,为什么?
// -因为可能o本来是没有左边的儿子的,一交换以后就有了,所以要先down().
o->down();
while(o->ch[] != nill)
{
o = o->ch[];
o->down();
}
return o;
} void Reverse(int a,int b)
{
node* x = findK(root,a);
node* y = findK(root,b+);
x->splay();
y->splay(root);
tochange->rev ^= ;
} void Cut(int a,int b,int c)
{
node* x = findK(root, a);
node* y = findK(root, b+);
x->splay();
y->splay(root);
node* temp = tochange;
y->setc(nill, );
node* z = findK(root, c+);
z->splay();
z = get_min(root->ch[]);
z->splay(root);
root->ch[]->setc(temp, );
} int n,m;
node* newNode(int val = )
{
node* o = bat ++;
o->init(val);
return o;
}
void init()
{
bat = memo;
nill = newNode(); nill->sz = ;
root = newNode(); root->fa = nill;
node* p = newNode(), *p2 = nill;
root->setc(p, );
p = nill;
for(int i=;i<=n;i++)
{
p2 = newNode(i);
p2->setc(p, );
p = p2;
}
root->ch[]->setc(p, );
} int cnt = ;
void print(node* o)
{
if(o == nill) return ;
o->down();
print(o->ch[]);
if(cnt >= && cnt <= n)
{
if(cnt > ) printf(" ");
printf("%d",o->val);
}
cnt++;
print(o->ch[]);
} int main()
{
while(scanf("%d%d",&n,&m) == )
{
if(n == - && m == -) break;
init(); char s[];
while(m--)
{
scanf("%s",s);
if(s[] == 'F')
{
int a,b;scanf("%d%d",&a,&b);
Reverse(a,b);
}
else
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Cut(a,b,c);
}
}
cnt = ;
print(root);
puts("");
}
}

Splay区间翻转+区间切割

  然后A题,可以直接map写,然后弹出最大最小就可以了。为了练手Splay,特地用Splay写了一遍(惊喜的是时间比map的要短= =)。

 #include <stdio.h>
#include <algorithm>
#include <string.h>
#define tochange (root->ch[1]->ch[0])
using namespace std;
const int N = + ;
struct node *nill, *root;
struct node {
int val, key;
int sz;
bool rev;
node *ch[],*fa;
void init(int v,int p)
{
ch[] = ch[] = fa = nill;
val = v;
key = p;
sz = ;
}
void up() {
if (this==nill) return ;
sz = ch[]->sz + ch[]->sz + ;
}
void down() {
if (this==nill) return ;
if(rev)
{
rev = false;
ch[]->rev ^= ;
ch[]->rev ^= ;
swap(ch[], ch[]);
}
}
bool d() {
return fa->ch[]==this;
}
void reverse() {
rev ^= ;
std::swap(ch[],ch[]);
}
void setc(node *o,int c) {
ch[c] = o;
o->fa = this;
up();
}
void rot() {
int c = d(),cc = fa->d();
node *z = fa->fa;
node *tmp = fa;
fa->setc(ch[c^],c);
setc(tmp,c^);
if(z!=nill) z->setc(this,cc);
else fa = z;
}
void D() {
if (this==nill) return ;
fa->D();
down();
}
void splay(node *aim = nill) {
D();
while (fa!=aim) {
if (fa->fa!=aim) {
d()==fa->d() ? fa->rot() : rot();
}
rot();
}
if(aim == nill) root = this;
}
}memo[N], *bat; node* newNode()
{
node* o = bat ++;
return o;
}
void init()
{
bat = memo;
nill = newNode(); nill->sz = ;
root = nill;
} void _insert(node* o, node* p)
{
if(p->key < o->key)
{
if(o->ch[] == nill) {o->setc(p, );return ;}
else _insert(o->ch[], p);
}
else if(p->key > o->key)
{
if(o->ch[] == nill) {o->setc(p, );return ;}
else _insert(o->ch[], p);
}
}
void insert(int val,int key)
{
node* p = newNode();
p->init(val, key);
if(root == nill) root = p;
else _insert(root, p);
} node* get_max_or_min(node* o, int op)
{
//o->down();
while(o->ch[op] != nill)
{
o = o->ch[op];
//o->down();
}
return o;
}
// 1->pop_max, 0->pop_min
void pop_max_or_min(int op)
{
if(root == nill) {printf("0\n");return;}
node* p = get_max_or_min(root, op);
p->splay(nill);
printf("%d\n",p->val);
root = p->ch[op^];
root->fa = nill;
} int main()
{
init();
int n;
while(scanf("%d",&n) == && n)
{
if(n == )
{
int val, key;scanf("%d%d",&val,&key);
insert(val,key);
}
else if(n == ) pop_max_or_min();
else pop_max_or_min();
}
return ;
}

Splay维护最大或最小key的节点

  

  然后,,因为要复习了,暂时就放放了。。

ACM之路(20)—— Splay初探的更多相关文章

  1. nyist 606 ACM之路

    http://acm.nyist.net/JudgeOnline/problem.php?pid=606 ACM之路 时间限制:1000 ms | 内存限制:65535 KB 描述 转眼间,12级新生 ...

  2. ACM之路(19)—— 主席树初探

    长春赛的 I 题是主席树,现在稍微的学了一点主席树,也就算入了个门吧= = 简单的来说主席树就是每个节点上面都是一棵线段树,但是这么多线段树会MLE吧?其实我们解决的办法就是有重复的节点给他利用起来, ...

  3. ACM之路

    从10月我刚接触到acm竞赛,到现在2017年2.20接近4个月的时间,我才刷到200道题.在刷题的过程中,我曾遇到困难,我也从一次性就a过,但是有时候会想到放弃.不过既然已经踏进来一只脚,还不如就好 ...

  4. 另一个ACM之路建议

    ACM联系建议 一位高手对我的建议: 一般要做到50行以内的程序不用调试.100行以内的二分钟内调试成功.acm主要是考算法的 ,主要时间是花在思考算法上,不是花在写程序与debug上. 下面给个计划 ...

  5. ACM之路——上车了

    校赛坚持到底,拿到了银牌:第一批进入ACM队集训,期末考试之前仍然代码不断,甚至感觉对不起大学第一次的期末考试,五天复习高数,两天复习英语,看到英语成绩是胸口突然好痛,好难受……就为了成为ACM正式队 ...

  6. 剪辑的楼天城的ACM之路

    楼天城楼教主的acm心路历程(剪辑) 利用假期空闲之时,将这几年GCJ,ACM,TopCoder 参加的一些重要比赛作个回顾.昨天是GCJ2006 的回忆,今天时间上更早一些吧,我现在还清晰记得3 年 ...

  7. ACM之路(转载)

    转载自:https://www.cnblogs.com/tianjintou/p/4139416.html 要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来. 适合自己的才是好的,有的人 ...

  8. Android开发学习之路-RecyclerView使用初探

    在进行一些MaterialDesign规范开发的时候,比如之前说到的CoordinateLayout实现的向上折叠效果的时候,如果依然使用ListView,那么这种效果是做不出来的,因为ListVie ...

  9. NOIP2012 借教室 Splay初探

    终于把区间操作的Splay搞明白了…… Splay的大致框架是这样的: [代码中的Zig-Zig和Zig-Zag操作其实是可以优化的,实际只需要3次passDown和3次update] templat ...

随机推荐

  1. vue.js 2.0开发(4)

    使用vue-cli,首先安装: npm install -g vue-cli 安装完了执行vue命令,会出现 vue init <template-name> <project-na ...

  2. React组件的分类

    * 1.statelessComponent 不包含任何state的组件 例如:AntDesign的 :Button,Input组件 * 2.viewComponent 包含少量ui state的组件 ...

  3. 由system.currentTimeMillis() 获得当前的时间

    System类代表系统,系统级的很多属性和控制方法都放置在该类的内部.该类位于java.lang包. currentTimeMillis方法 public static long currentTim ...

  4. IIS发布问题汇总

    1.未能加载文件或程序集“System.Data.SQLite” 在IIS界面选择应用程序池->选择所使用的.net 版本->高级设置->将"使用32位应用程序" ...

  5. iptables删除规则

    查看nat规则: iptables -t nat -nL --line-number 添加规则是-A和-I,-A是添加到末尾,-I是添加到指定位置,默认添加到最前面.删除使用-D,也就是原来“ipta ...

  6. KNN算法——python实现

    二.Python实现 对于机器学习而已,Python需要额外安装三件宝,分别是Numpy,scipy和Matplotlib.前两者用于数值计算,后者用于画图.安装很简单,直接到各自的官网下载回来安装即 ...

  7. Linux学习二:Makefile基础

    文首感谢http://www.chinaunix.net 作者:gunguymadman的分享 makefile关系到了整个工程的编译规则.一个工程中的源文件不计数,其按类型.功能.模块分别放在若干个 ...

  8. c#与js中10进制16进制的转化,记录防忘

    js: var param="11"; param=parseInt(param,16);  //17 param=parseInt(param,10);  //11 //后面的参 ...

  9. AX7: HOW TO USE CLASS EXTENSION METHODS

    AX7: HOW TO USE CLASS EXTENSION METHODS   To create new methods on a standard AX class without custo ...

  10. Eclipse+MinGW+Boost环境搭建

    一.编译 运行 .bat 生成bjam.exe 运行:bjam --build-type=complete toolset=gcc stage 二.配置 配置eclipse -L Path加入链接库位 ...