点操作:

splay树可以一个一个的插入结点,这样的splay树是有序树,结点权值大于左儿子小于右儿子

这样就是点操作

区间操作:

还有就是可以自己建树,这样的splay树就不是按权值的有序树,它不满足结点权值大于左儿子小于右儿子,,

但是它也是有顺序的,无论怎么伸展,把它的结点中序遍历结果就是原来的数组顺序。

因此自己建树可以操作区间!

点操作模板

// File Name: ACM/bzoj/1208.cpp
// Author: Zlbing
// Created Time: 2013年08月08日 星期四 16时33分53秒 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
const int MAXN=8e4+;
const int mod=;
struct SplayTree {
int sz[MAXN];
int ch[MAXN][];
int pre[MAXN];
int rt,top;
inline void up(int x){
sz[x] = cnt[x] + sz[ ch[x][] ] + sz[ ch[x][] ];
}
inline void Rotate(int x,int f){
int y=pre[x];
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x]) ch[ pre[y] ][ ch[pre[y]][] == y ] =x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
inline void Splay(int x,int goal){//将x旋转到goal的下面
while(pre[x] != goal){
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][] == x);
else {
int y=pre[x],z=pre[y];
int f = (ch[z][]==y);
if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
up(x);
if(goal==) rt=x;
}
inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
int x=rt;
while(sz[ ch[x][] ] != k-) {
if(k < sz[ ch[x][] ]+) x=ch[x][];
else {
k-=(sz[ ch[x][] ]+);
x = ch[x][];
}
}
Splay(x,goal);
}
inline void vist(int x){
if(x){
printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d sz=%d\n",x,ch[x][],ch[x][],val[x],sz[x]);
vist(ch[x][]);
vist(ch[x][]);
}
}
inline void Newnode(int &x,int c){
x=++top;
ch[x][] = ch[x][] = pre[x] = ;
sz[x]=; cnt[x]=;
val[x] = c;
}
inline void init(){
ans=;type=-;
ch[][]=ch[][]=pre[]=sz[]=;
rt=top=; cnt[]=;
Newnode(rt,-INF);
Newnode(ch[rt][],INF);
pre[top]=rt;
sz[rt]=;
}
inline void Insert(int &x,int key,int f){
if(!x) {
Newnode(x,key);
pre[x]=f;
Splay(x,);
return ;
}
if(key==val[x]){
cnt[x]++;
sz[x]++;
return ;
}else if(key<val[x]) {
Insert(ch[x][],key,x);
} else {
Insert(ch[x][],key,x);
}
up(x);
} void Del(){ //删除根结点
      int t=rt;
if(ch[rt][]) {
rt=ch[rt][];
RTO(,);
ch[rt][]=ch[t][];
if(ch[rt][]) pre[ch[rt][]]=rt;
}
else rt=ch[rt][];
pre[rt]=;
up(rt);
}
void findpre(int x,int key,int &ans){ //找key前趋
if(!x) return ;
if(val[x] <= key){
ans=x;
findpre(ch[x][],key,ans);
} else
findpre(ch[x][],key,ans);
}
void findsucc(int x,int key,int &ans){ //找key后继
if(!x) return ;
if(val[x]>=key) {
ans=x;
findsucc(ch[x][],key,ans);
} else
findsucc(ch[x][],key,ans);
}
  
//找第K大数
inline int find_kth(int x,int k){
if(k<sz[ch[x][]]+) {
return find_kth(ch[x][],k);
}else if(k > sz[ ch[x][] ] + cnt[x] )
return find_kth(ch[x][],k-sz[ch[x][]]-cnt[x]);
else{
Splay(x,);
return val[x];
}
}

int cnt[MAXN];
int val[MAXN];
int type;
int ans;
}spt;
int main()
{
int n;
while(~scanf("%d",&n))
{
spt.init();
int a,b;
int ans=;
int type=-;
REP(i,,n)
{
scanf("%d%d",&a,&b);
if(a==type||spt.sz[spt.rt]==)
{
spt.Insert(spt.rt,b,);
type=a;
//spt.vist(spt.rt);
}
else
{
int x,y;
if(spt.sz[spt.rt]==)continue;
spt.findpre(spt.rt,b,x);
spt.findsucc(spt.rt,b,y);
if(abs(spt.val[x]-b)<=abs(spt.val[y]-b))
{
ans+=abs(spt.val[x]-b);
ans%=mod;
spt.Splay(x,);
//spt.vist(spt.rt);
spt.Del();
}
else{
ans+=abs(spt.val[y]-b);
ans%=mod;
spt.Splay(y,);
//spt.vist(spt.rt);
spt.Del();
}
}
}
printf("%d\n",ans);
}
return ;
}

区间操作模板

// File Name: ACM/HDU/3487.cpp
// Author: Zlbing
// Created Time: 2013年08月10日 星期六 21时35分28秒 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
#define L ch[x][0]
#define R ch[x][1]
#define KT (ch[ ch[rt][1] ][0])
const int MAXN = 3e5+;
struct SplayTree {
int sz[MAXN];
int ch[MAXN][];
int pre[MAXN];
int rt,top;
inline void down(int x){
if(flip[x]) {
flip[ L ] ^= ;
flip[ R ] ^= ;
swap(L,R);
flip[x]=;
}
}
inline void up(int x){
sz[x]=+sz[ L ] + sz[ R ];
}
inline void Rotate(int x,int f){
int y=pre[x];
down(y);
down(x);
ch[y][!f] = ch[x][f];
pre[ ch[x][f] ] = y;
pre[x] = pre[y];
if(pre[x]) ch[ pre[y] ][ ch[pre[y]][] == y ] =x;
ch[x][f] = y;
pre[y] = x;
up(y);
}
inline void Splay(int x,int goal){//将x旋转到goal的下面
down(x);////防止pre[x]就是目标点,下面的循环就进不去了,x的信息就传不下去了
while(pre[x] != goal){
down(pre[pre[x]]); down(pre[x]);down(x);//在旋转之前需要先下传标记,因为节点的位置可能会发生改变
if(pre[pre[x]] == goal) Rotate(x , ch[pre[x]][] == x);
else {
int y=pre[x],z=pre[y];
int f = (ch[z][]==y);
if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f);
else Rotate(y,f),Rotate(x,f);
}
}
up(x);
if(goal==) rt=x;
}
inline void RTO(int k,int goal){//将第k位数旋转到goal的下面
int x=rt;
down(x);
while(sz[ L ]+ != k) {
if(k < sz[ L ] + ) x=L;
else {
k-=(sz[ L ]+);
x = R;
}
down(x);
}
Splay(x,goal);
}
void vist(int x){
if(x){
printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d flip:%d\n",x,L,R,val[x],flip[x]);
vist(L);
vist(R);
}
}
void Newnode(int &x,int c,int f){
x=++top;flip[x]=;
L = R = ; pre[x] = f;
sz[x]=; val[x]=c;
}
inline void build(int &x,int l,int r,int f){
if(l>r) return ;
int m=(l+r)>>;
Newnode(x,m,f);
build(L , l , m- , x);
build(R , m+ , r , x);
pre[x]=f;
up(x);
} inline void init(int n){
ch[][]=ch[][]=pre[]=sz[]=;
rt=top=; flip[]=; val[]=;
Newnode(rt,-,);
Newnode(ch[rt][],-,rt);
sz[rt]=;
build(KT,,n,ch[rt][]);
}
//删除根结点
void Del(){
int t=rt;
if(ch[rt][]) {
rt=ch[rt][];
RTO(,);
ch[rt][]=ch[t][];
if(ch[rt][]) pre[ch[rt][]]=rt;
}
else rt=ch[rt][];
pre[rt]=;
up(rt);
}
//把[a,b]放在c的后面
void solve1(int a,int b,int c)
{
RTO(a,);
RTO(b+,rt);
int tmp=KT;
KT=;
up(ch[rt][]);
up(rt); RTO(c+,);
RTO(c+,rt);
KT=tmp;
pre[tmp]=ch[rt][];
up(ch[rt][]);
up(rt);
}
//翻转[a,b]
void solve2(int a,int b)
{
RTO(a,);
RTO(b+,rt);
flip[KT]^=;
}
void print(int x)
{
if(x)
{
down(x);
print(L);
if(val[x]!=-)
{
if(flag)printf(" ");
flag=;
printf("%d",val[x]);
}
print(R);
}
}
void out()
{
flag=;
print(rt);
printf("\n");
}
int flip[MAXN];
int val[MAXN];
int flag;
}spt; int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
if(n==-)break;
char op[];
int a,b,c;
spt.init(n);
REP(i,,m)
{
scanf("%s",op);
if(op[]=='C')
{
scanf("%d%d%d",&a,&b,&c);
spt.solve1(a,b,c);
}
else
{
scanf("%d%d",&a,&b);
spt.solve2(a,b);
} }
spt.out();
}
return ;
}

splay模板的更多相关文章

  1. bzoj 1588 splay模板题

    用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... #include<iostream> #include<cstdio> ...

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

    我的LCC,LCT,Splay格式终于统一起来了... 另外..这个形式的Splay是标准的Splay(怎么鉴别呢?看Splay函数是否只传了一个变量node就行),刘汝佳小白书的Splay写的真是不 ...

  3. Splay 模板

    Splay 模板 struct SplayTree{ const static int maxn = 1e5 + 15; int ch[maxn][2] , key[maxn] , s[maxn] , ...

  4. [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)

    解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...

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

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][S ...

  6. 文艺平衡树(splay模板)

    题干:splay模板,要求维护区间反转. splay是一种码量小于treap,但支持排名,前驱后继等treap可求的东西,也支持区间反转的平衡树. 但是有两个坏处: 1.splay常数远远大于trea ...

  7. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  8. bzoj 1208 splay模板题2

    自己yy了找前驱和后继,学了学怎么删除...(反正就是练模板) #include<iostream> #include<cstdio> #include<cstring& ...

  9. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  10. 【BZOJ 3188】【Coci 2011】Upit Splay模板题

    转啊转终于转出来了,然而我的模板跟陈竞潇学长的模板一模一样,还是太弱啊,第一次用指针. #include<cstdio> #include<cstring> #include& ...

随机推荐

  1. Eclipse3.7默认字体修改-找回Courser-New字体

    1.找到jFace并用WinRAR打开之: jFace的具体位置:$Eclipse目录$/plugins/org.eclipse.jface_3.7.0.I20110522-1430.jar,找到后, ...

  2. Java基础知识强化99:Java 常见异常及趣味解释

    常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎:) 1. java.langjava.lang软件包是java语言的核心部分,它提供了java中的基础类. java.lan ...

  3. error: device not found - waiting for device -

    执行 cocos run -p android 时报的这个错误 连接上 android 手机, 手机开启开发者模式.  设置--其他高级设置--开发者选项--USB 调试

  4. POS tagging的解釋

    轉錄文章~~ 什么是词性标注(POS tagging) Tue, 04/13/2010 - 10:36 — Fuller 词性标注也叫词类标注,POS tagging是part-of-speech t ...

  5. PL/SQL Developer远程连接Oracle数据库

    首先打开电脑,到pl/sql安装的指定目录[D:\app\DZL\product\11.2.0\dbhome_1\NETWORK\ADMIN]找到[tnsnames.ora]     打开[tnsna ...

  6. magic_quotes_gpc、mysql_real_escape_string、addslashes的区别及用法

    本篇文章,主要先重点说明magic_quotes_gpc.mysql_real_escape_string.addslashes 三个函数方法的含义.用法,并举例说明.然后阐述下三者间的区别.关系.一 ...

  7. 寒哥教你学 iOS - 经验漫谈(转)

    转自http://www.cocoachina.com/ios/20150907/13339.html 本篇文章主要讲解 4个问题 load妙用 aop面向切面编程 NSNumber Or Int @ ...

  8. JS入门笔记

    DOM有四种节点: 1. 元素节点:即标签2. 属性节点:写在标签里的属性3. 文本节点:嵌在元素节点里展示出来的文本4. 文档节点:document 获取元素节点的三种常用方法: 1.ById 2. ...

  9. js判断是否在iframe中

    1.方式一 if (self.frameElement && self.frameElement.tagName == "IFRAME") { alert('在if ...

  10. String、StringBuffer、StringBuilder

    也说String. String:不可变字符序列. StringBuffer:线程安全的可变字符序列. StringBuilder:StringBuffer的非线程安全实现,JDK1.5+. publ ...