【整合】Splay模板

用了两天时间学了Splay+搞自己的模板

最后应该算是搞完了吧。

虽然可能还是有很多不太完美的地方OTZ

总感觉单纯维护集合还是sbt更好用QUQ(要不是为了做区间才不学Splay呢!)

指针各种难调试啊OTZ

一个remove调了一天(╯‵□′)╯︵┻━┻

以后除非是区间否则坚决不想用的东西(常数还比sbt大那么多=0=)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define P 1000000
#define MAXINT 100000000000
using namespace std;
struct splay
{
	splay *ch[2],*fa;//ch[0]为左子树ch[1]为右子树fa为父节点
	int data,cnt,size;//data节点数值cnt重复元素个数size树的大小
}*root,*no;
int ans;
int n,key,flag,pet,human;
void calc(splay *x)
{
	x->size=x->cnt;
	if (x->ch[0]) x->size+=x->ch[0]->size;
	if (x->ch[1]) x->size+=x->ch[1]->size;
}
void rot(splay *x,bool flag)//flag=0左旋flag=1右旋 节省编程复杂度的小优化
{
	splay *y=x->fa;
	y->ch[!flag]=x->ch[flag];
    if (x->ch[flag]!=NULL) x->ch[flag]->fa=y;
	x->fa=y->fa;
	if (y->fa!=NULL)
	    if (y->fa->ch[0]==y) y->fa->ch[0]=x;
	    else y->fa->ch[1]=x;
	x->ch[flag]=y;
	y->fa=x;
	if (y==root) root=x;
}
void Splay(splay *x,splay *f)//将节点X提到节点f下 (地位与sbt Maintain()相同的操作0-0)
{
	if (x==f||x==NULL) return;
	while (x->fa!=f)
	{
		if (x->fa->fa==f)
		{
			if (x->fa->ch[0]==x) rot(x,1);
		    else rot(x,0);
		}
		else
		{
			splay *y=x->fa,*z=y->fa;
			if (z->ch[0]==y)
			    if (y->ch[0]==x)
			        rot(y,1),rot(x,1);
			    else
			        rot(x,0),rot(x,1);
			else
			    if (y->ch[0]==x)
			        rot(x,1),rot(x,0);
			    else
			        rot(y,0),rot(x,0);
		}
	}
	if (f==NULL) root=x;
	if (x!=NULL)calc(x);
	if (f!=NULL)calc(f);
}
void insert(int data)
{
	splay *n=root,*x=NULL;
	while (n!=NULL)
	{
		x=n;
		if (data>=n->data) n=n->ch[1];
		else n=n->ch[0];
	}
	n=new splay;
	n->ch[0]=n->ch[1]=NULL;
	n->size=1;
	n->data=data;
	n->cnt=1;
	n->fa=x;
	if (x==NULL) root=n;
	else
	if (data>=x->data) x->ch[1]=n;
	else x->ch[0]=n;
	if (n!=root) Splay(n,NULL);
}
splay* find(int data)
{
	if (root==NULL) return NULL;
	splay *x=root,*y=NULL;
	while (x!=NULL)
	{
		if (data>x->data)
		    y=x,x=x->ch[1];
		else
		if (data<x->data)
		    y=x,x=x->ch[0];
		else
		    {
		    	y=x;
		    	return y;
		    }
	}
	return NULL;
}
splay* getmax()
{
	if (root==NULL) return NULL;
	splay *x=root;
	while (x->ch[1]) x=x->ch[1];
	return x;
}
splay* getmin()
{
	if (root==NULL) return NULL;
	splay *x=root;
	while (x->ch[0]) x=x->ch[0];
	return x;
}
int rank(int data)
{
	splay *x=find(data);
	Splay(x,root);
	if (root->ch[0]==x) return x->ch[0]->size+1;
	else
	return root->ch[0]->size+1+x->ch[0]->size+1;
}
splay* select(int k)
{
	splay *x=root;
	while (x)
	{
		if (k>x->ch[0]->size+1)
		{
			k-=x->ch[0]->size+1;
			x=x->ch[1];
		}
		else
		if (k<x->ch[0]->size+1)
		{
			x=x->ch[0];
		}
		else
		    return x;
	}
}
splay* pred(splay *x,splay *y,int data)
{
	if (x==NULL) return y;
	if (data==x->data) return y;
	if (data>x->data) return pred(x->ch[1],x,data);
	else return pred(x->ch[0],y,data);
}
splay* succ(splay *x,splay *y,int data)
{
	if (x==0) return y;
	if (x->data==data) return x;
	if (x->data>data) return succ(x->ch[0],x,data);
	else return succ(x->ch[1],y,data);
}
void remove(int data)
{
	if (root==NULL) return;
	splay *x=find(data),*y;
	if (x==NULL) return;
	Splay(x,NULL);
	if (!x->ch[0]&&!x->ch[1]) root=NULL;
	if (x->ch[0]&&!x->ch[1]) root=x->ch[0],x->ch[0]->fa=NULL;
	if (!x->ch[0]&&x->ch[1]) root=x->ch[1],x->ch[1]->fa=NULL;
	if (x->ch[0]&&x->ch[1])
	{
		y=x->ch[1];
		while (y->ch[0]) y=y->ch[0];
		Splay(y,NULL);
		y->fa=NULL;
		y->ch[0]=x->ch[0];
		x->ch[0]->fa=y;
		calc(y);
		root=y;
	}
}
/*int main()
{
}/*
时间: 2024-10-14 12:00:16

【整合】Splay模板的相关文章

splay模板

先贴一份不怎么完善的模板,等刷一些题目熟悉之后再来完善.代码参考自kuangbin及cxlove两位大神. splay的基本功能 题目:维护一个数列,支持以下几种操作: 1. 插入:在当前数列第posi 个数字后面插入tot 个数字:若在数列首位插入,则posi 为0. 2. 删除:从当前数列第posi 个数字开始连续删除tot 个数字. 3. 修改:从当前数列第posi 个数字开始连续tot 个数字统一修改为c . 4. 翻转:取出从当前数列第posi 个数字开始的tot 个数字,翻转后放入原

bzoj 1588 splay模板题

用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 33333 6 #define inf 0x3f3f3f3f 7 #define lc(x) ch[(x)][0] 8 #define rc(x) ch[(x)

bzoj1500(妥妥的splay模板题)

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 6366  Solved: 1910 [Submit][Status] Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次

COJ 1002 WZJ的数据结构(二)(splay模板)

我的LCC,LCT,Splay格式终于统一起来了... 另外..这个形式的Splay是标准的Splay(怎么鉴别呢?看Splay函数是否只传了一个变量node就行),刘汝佳小白书的Splay写的真是不想吐槽了,局限性太大,别学... 好了我要去写维修数列了..... 标准Splay模板: 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #inc

BZOJ1588 [HNOI2002]营业额统计 splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

ThinkPHP3.2.3整合smarty模板(二)

前言:继ThinkPHP3.2.3整合smarty模板(一)之后,继续来探讨一下tp框架整合smarty模板,看到有人在群上问到怎么使用自定义的常量,今天就具体来谈谈: 一.开发一个项目,必不可少会用到很多的自定义常量,比如定义一些常量作为引入静态文件,但在smarty模板中怎么直接使用这些常量呢? 1.定义常量:如:define('__IMAGE__', __STATIC__ . '/img'),在入口文件定义或者其他文件定义这个都无所谓,若在其他文件定义,则需要引入一下; 2.在模板中使用常

文艺平衡树(splay模板)

题干:splay模板,要求维护区间反转. splay是一种码量小于treap,但支持排名,前驱后继等treap可求的东西,也支持区间反转的平衡树. 但是有两个坏处: 1.splay常数远远大于treap以及stl中的set. 2.没有可持久化splay,但有可持久化treap. 下面是代码: 1.pushup以及pushdown pushup用于维护某点所在子树大小. void pushup(int u) { tr[u].siz = tr[tr[u].ch[0]].siz + tr[tr[u].

ThinkPHP3.2.3整合smarty模板(一)

一.php模板引擎有哪些? 1.1 PHPLIB:一套古老且主流的模板引擎,直接在html中使用PHP变量进行编程: 1.2 Template Blocks:一款轻巧且速度非常快的PHP模板引擎,支持xml语法: 1.3 TinyButStrong:肖墙模板,业界非常著名好用的模板引擎,直接支持Dreamweaver插件编辑: 1.4 Rain TPL:易于使用和安装引擎,有6个标签,3个PHP函数和2个PHP类,支持对模板中的相对路径自动转换为绝对路径: 1.5 PHPTAL:是一个ZPT的P

伸展树 Splay 模板

学习Splay的时候参考了很多不同的资料,然而参考资料太杂的后果就是模板调出来一直都有问题,尤其是最后发现网上找的各种资料均有不同程度的错误. 好在啃了几天之后终于算是啃下来了. Splay也算是平衡树的一种,但是跟AVL树.SBT不同的是,Splay并不是一直保持严格的平衡,因此在速度上可能要慢一些,但是统计学上仍能保证Splay具有O(logn)的均摊复杂度. Splay原生不需要附加任何空间,它的先天优势是其特有的Splay操作可以非常灵活地改变整棵树的结构形态,完成一般线段树.平衡树做不