1, splay的一些基本操作.

  • 使用前要插入$-INF,+INF$保证每个点的前驱后继存在.
  • $get$函数在$x$存在时, 调用后, 根为$x$, 否则根为$x$的前驱或后继
const int N = 1e6+10;
int n, tot, rt, sz;
struct {
int cnt,sz,fa,ch[2],v;
} tr[N];
void pu(int x) {
tr[x].sz=tr[tr[x].ch[0]].sz+tr[tr[x].ch[1]].sz+tr[x].cnt;
}
void rot(int x) {
int y=tr[x].fa,z=tr[y].fa;
int f=tr[y].ch[1]==x;
tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa=z;
tr[y].ch[f]=tr[x].ch[f^1],tr[tr[x].ch[f^1]].fa=y;
tr[x].ch[f^1]=y,tr[y].fa=x,pu(y);
}
void splay(int x, int s=0) {
for (int y; y=tr[x].fa,y!=s; rot(x)) if (tr[y].fa!=s) {
rot((tr[y].ch[0]==x)==(tr[tr[y].fa].ch[0]==y)?y:x);
}
if (!s) rt=x;
}
void get(int x) {
int cur=rt;
while (x!=tr[cur].v&&tr[cur].ch[x>tr[cur].v]) cur=tr[cur].ch[x>tr[cur].v];
splay(cur);
}
void insert(int x) {
int cur=rt,p=0;
while (cur&&x!=tr[cur].v) p=cur,cur=tr[cur].ch[x>tr[cur].v];
if (cur) ++tr[cur].cnt;
else {
cur=++tot;
if (p) tr[p].ch[x>tr[p].v]=cur,tr[cur].fa=p;
tr[cur].v=x,tr[cur].sz=tr[cur].cnt=1;
}
splay(cur);
}
int pre(int x) {
get(x);
if (tr[rt].v<=x) return rt;
int cur=tr[rt].ch[0];
while (tr[cur].ch[1]) cur=tr[cur].ch[1];
return cur;
}
int nxt(int x) {
get(x);
if (tr[rt].v>=x) return rt;
int cur=tr[rt].ch[1];
while (tr[cur].ch[0]) cur=tr[cur].ch[0];
return cur;
}
void erase(int x) {
int s1=pre(x-1),s2=nxt(x+1);
splay(s1),splay(s2,s1);
int &cur=tr[s2].ch[0];
if (tr[cur].cnt>1) --tr[cur].cnt,splay(cur);
else cur=0;
}

2, splay插入区间,区间翻转等操作.

这时候splay维护的是每个下标对应的权值, 下标通过第k大来查询

  • 使用前要调用$build(a,0,rt,1,2);$
const int N = 1e6+10;
int n, rt, tot;
int a[N];
struct _ {
int sz,v,ch[2],fa,rev;
} tr[N];
void pu(int o) {
tr[o].sz=tr[tr[o].ch[0]].sz+tr[tr[o].ch[1]].sz+1;
}
void pd(int o) {
if (tr[o].rev) {
swap(tr[o].ch[0],tr[o].ch[1]);
tr[tr[o].ch[0]].rev^=1;
tr[tr[o].ch[1]].rev^=1;
tr[o].rev=0;
}
}
void rot(int x) {
int y=tr[x].fa,z=tr[y].fa;
int f=tr[y].ch[1]==x;
tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa=z;
tr[y].ch[f]=tr[x].ch[f^1],tr[tr[x].ch[f^1]].fa=y;
tr[x].ch[f^1]=y,tr[y].fa=x,pu(y);
}
void splay(int x, int s=0) {
for (int y; y=tr[x].fa,y!=s; rot(x)) if (tr[y].fa!=s) {
rot((tr[y].ch[0]==x)==(tr[tr[y].fa].ch[0]==y)?y:x);
}
if (!s) rt=x;
}
int find(int x, int k) {
pd(x); int s=tr[tr[x].ch[0]].sz;
if (k==s+1) return x;
if (k<=s) return find(tr[x].ch[0],k);
return find(tr[x].ch[1],k-s-1);
}
void build(int *a, int f, int &o, int l, int r) {
if (l>r) return;
o = ++tot;
tr[o].v = a[mid], tr[o].fa = f;
build(s,o,tr[o].ch[0],l,mid-1);
build(s,o,tr[o].ch[1],mid+1,r);
pu(o);
}
void ins(int x, int n) {
build(a,0,p,1,n);
int s1=find(rt,x-1), s2=find(rt,x);
splay(s1),splay(s2,s1);
tr[s2].ch[0]=p,tr[p].fa=s2;
pu(p),pu(s2);
}
void del(int x, int n) {
int s1=find(rt,x-1), s2=find(rt,x+n);
splay(s1),splay(s2,s1);
tr[s2].ch[0]=0;
pu(s1),pu(s2);
}
void reverse(int x, int n) {
int s1=find(rt,x-1), s2=find(rt,x+n);
splay(s1),splay(s2,s1);
tr[tr[s2].ch[0]].rev^=1;
}

splay板子的更多相关文章

  1. [bzoj] 1588 营业额统计 || Splay板子题

    原题 给出一个n个数的数列ai ,对于第i个元素ai定义\(fi=min(|ai-aj|) (1<=j<i)\),f1=a1,求\(/sumfi\) Splay板子题. Splay讲解:h ...

  2. POJ - 3481 splay板子

    Double Queue 默写splay板子 很多细节问题... #include<cstdio> #include<iostream> using namespace std ...

  3. 个人整理的数组splay板子,指针的写的太丑了就不放了。。

    splay的板子.. 由于被LCT榨干了..所以昨天去学了数组版的splay,现在整理一下板子.. 以BZOJ3224和3223为例题..暂时只有这些,序列的话等有时间把维修序列给弄上来!! BZOJ ...

  4. bzoj3224 splay板子

    开始学习新知识:splay——tree 是个板子题,学习splay可以看博客 https://blog.csdn.net/Clove_unique/article/details/50630280 # ...

  5. BZOJ 3224 Tyvj 1728 普通平衡树 | Splay 板子+SPlay详细讲解

    下面给出Splay的实现方法(复杂度证明什么的知道是 nlogn 就可以啦) 首先对于一颗可爱的二叉查找树,是不能保证最坏nlogn的复杂度(可以想象把一个升序序列插入) (二叉查找树保证左子树元素大 ...

  6. BZOJ[NOI2004]郁闷的出纳员 | Splay板子题

    题目: 洛谷也能评测....还有我wa了10多次的记录233 题解: 不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x- ...

  7. P3369 【模板】普通平衡树(splay)

    P3369 [模板]普通平衡树 就是不用treap splay板子,好好背吧TAT #include<iostream> #include<cstdio> #include&l ...

  8. 【题解】 [HNOI2004]宠物收养场(Splay)

    懒得复制,戳我戳我 Solution: \(Splay\)板子,注意交换的地方,然后就是注意不要越界node[x],应该是\(node[now]\),其次就是数组可以开大点 Code: //It is ...

  9. 【题解】 [HNOI2002]营业额统计 (Splay)

    懒得复制,戳我戳我 Solution: \(Splay\)板子题,注意可以选择相等大小 Code: //It is coded by Ning_Mew on 4.10 #include<bits ...

随机推荐

  1. Python中的is和==的区别,==判断值是否相等,is判断地址是否一致

    Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...

  2. Js基础知识7-JavaScript所有内置对象属性和方法汇总

    对象什么的,程序员可是有很多呢... JS三大对象 对象,是任何一个开发者都无法绕开和逃避的话题,她似乎有些深不可测,但如此伟大和巧妙的存在,一定值得你去摸索.发现.征服. 我们都知道,JavaScr ...

  3. SVN版本服务器搭建

    windows:        https://blog.csdn.net/lu1024188315/article/details/74082227 SVN 的下载地址如下 http://torto ...

  4. 浅谈elasticsearch 集群

    elasticsearch 集群 摘要: elasticsearch 集群 搭建elasticsearch的集群 现在假设我们有3台es机器,想要把他们搭建成为一个集群 基本配置 每个节点都要进行这样 ...

  5. 深入JAVA注解之属性注解

    项目目录结构 实体类: package org.guangsoft.annotation.entity; import java.lang.annotation.ElementType; import ...

  6. 20145127《java程序设计》第二周学习总结

    本周我又对java程序进行了更进一步的学习.相比与上一周的学习内容的宏观,这一周的所学更加的系统和调理明确. 本周是对java基础语法的学习.首先,我先是认识类型与变量. Java可区分为基本类型和类 ...

  7. IPMB接口协议总结

    IPMB接口协议总结 IPMB,智能平台管理总线, 是ATCA(Advanced Telecom Computing Architecture)先进的电信计算平台的各FRU背板通讯的两组冗余I2C总线 ...

  8. POJ 1222 EXTENDED LIGHTS OUT(高斯消元)题解

    题意:5*6的格子,你翻一个地方,那么这个地方和上下左右的格子都会翻面,要求把所有为1的格子翻成0,输出一个5*6的矩阵,把要翻的赋值1,不翻的0,每个格子只翻1次 思路:poj 1222 高斯消元详 ...

  9. HDU 2204 Eddy's爱好(容斥原理dfs写法)题解

    题意:定义如果一个数能表示为M^k,那么这个数是好数,问你1~n有几个好数. 思路:如果k是合数,显然会有重复,比如a^(b*c) == (a^b)^c,那么我们打个素数表,指数只枚举素数,2^60 ...

  10. HDU1043 Eight(八数码:逆向BFS打表+康托展开)题解

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...