点操作:

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. iOS 高仿:花田小憩3.0.1

    前言 断断续续的已经学习Swift一年多了, 从1.2到现在的2.2, 一直在语法之间徘徊, 学一段时间, 工作一忙, 再捡起来隔段时间又忘了.思来想去, 趁着这两个月加班不是特别多, 就决定用swi ...

  2. empty函数PHP

    empty译为: adj.空的,空虚的,空洞的;空闲的,无效的,徒劳的;无聊的,愚蠢的;言语或行动空洞的 vt.(使)成为空的, 把…弄空;把…腾出来 vi.成为空的;流空 n.空车;空的东西 是PH ...

  3. dede 最近一天发布的文章标题前加hot

    {dede:list pagesize ='15'} <!-- 模板1 --> <div class="news_list tp_a setp1"> < ...

  4. 调优系列-tomcat调优

    http://www.360doc.com/content/14/1208/13/16070877_431273418.shtml 使用JMeter对Tomcat进行压力测试与Tomcat性能调优 n ...

  5. javascript ~~ 符号的使用

    其实是一种利用符号进行的类型转换,转换成数字类型 大概是这样滴: ~~true == 1 ~~false == 0 ~~"" == 0 ~~[] == 0 ~~undefined ...

  6. 一个初学者对CLSA.NET框架的使用心得

    什么是CSLA.NET框架? 今天在一个群里,有人问我什么是CSLA.NET,CSLA是Component-based, Scalable, Logical Architecture的简写,CSLA ...

  7. 【转】iOS使用NSMutableAttributedString实现富文本

    iOS使用NSMutableAttributedString实现富文本 在iOS开发中,常常会有一段文字显示不同的颜色和字体,或者给某几个文字加删除线或下划线的需求.之前在网上找了一些资料,有的是重绘 ...

  8. 【转】iOS-Core-Animation-Advanced-Techniques(二)

    原文: http://www.cocoachina.com/ios/20150104/10816.html 视觉效果和变换 (四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到 ...

  9. 获取当前页面的url

    var url = window.location.href; var b = url.substring(url.lastIndexOf('/')+1, url.length);

  10. SGU 106.Index of super-prime

    时间限制:0.25s 空间限制:4M 题目大意:                 在从下标1开始素数表里,下标为素数的素数,称为超级素数(Super-prime),给出一个n(n<=10000) ...