平衡树(Splay)模板
支持区间操作。
单点操作和区间操作分开使用,需要一起使用需要部分修改。
对应题目FJUTOJ2490
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int N=,INF=0x3f3f3f3f; struct Splay_Tree
{
struct Node
{
int val,Max,add,Size,son[];
bool rev;
void init(int _val)
{
val=Max=_val,Size=;
add=rev=son[]=son[]=;
}
} T[N];
int fa[N],root,tot; void pushDown(int x)
{
if(x==)return ;
if(T[x].add)
{
if(T[x].son[])
{
T[T[x].son[]].val+=T[x].add;
T[T[x].son[]].Max+=T[x].add;
T[T[x].son[]].add+=T[x].add;
}
if(T[x].son[])
{
T[T[x].son[]].val+=T[x].add;
T[T[x].son[]].Max+=T[x].add;
T[T[x].son[]].add+=T[x].add;
}
T[x].add=;
}
if(T[x].rev)
{
if(T[x].son[])T[T[x].son[]].rev^=;
if(T[x].son[])T[T[x].son[]].rev^=;
swap(T[x].son[],T[x].son[]);
T[x].rev=;
}
} void pushUp(int x)
{
T[x].Max=T[x].val,T[x].Size=;
if(T[x].son[])
{
T[x].Max=max(T[x].Max,T[T[x].son[]].Max);
T[x].Size+=T[T[x].son[]].Size;
}
if(T[x].son[])
{
T[x].Max=max(T[x].Max,T[T[x].son[]].Max);
T[x].Size+=T[T[x].son[]].Size;
}
} void Rotate(int x,int kind)
{
int y=fa[x],z=fa[y];
T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;
T[x].son[kind]=y,fa[y]=x;
T[z].son[T[z].son[]==y]=x,fa[x]=z;
pushUp(y);
} void Splay(int x,int goal)
{
if(x==goal)return ;
while(fa[x]!=goal)
{
int y=fa[x],z=fa[y];
pushDown(z),pushDown(y),pushDown(x);
int rx=T[y].son[]==x,ry=T[z].son[]==y;
if(z==goal)Rotate(x,rx);
else
{
if(rx==ry)Rotate(y,ry);
else Rotate(x,rx);
Rotate(x,ry);
}
}
pushUp(x);
if(goal==)root=x;
} int Select(int pos)
{
int u=root;
pushDown(u);
while(T[T[u].son[]].Size!=pos)
{
if(pos<T[T[u].son[]].Size)u=T[u].son[];
else
{
pos-=T[T[u].son[]].Size+;
u=T[u].son[];
}
pushDown(u);
}
return u;
} void update(int L,int R,int val)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
T[T[v].son[]].Max+=val;
T[T[v].son[]].val+=val;
T[T[v].son[]].add+=val;
} void Reverse(int L,int R)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
T[T[v].son[]].rev^=;
} int query(int L,int R)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
return T[T[v].son[]].Max;
} int build(int L,int R)
{
if(L>R)return ;
if(L==R)return L;
int mid=(L+R)>>,sL,sR;
T[mid].son[]=sL=build(L,mid-);
T[mid].son[]=sR=build(mid+,R);
fa[sL]=fa[sR]=mid;
pushUp(mid);
return mid;
} void init(int n)
{
T[].init(-INF),T[].init(-INF),T[n+].init(-INF);
for(int i=;i<=n+;i++)T[i].init();
root=build(,n+),fa[root]=;
fa[]=,T[].son[]=root,T[].Size=;
} inline void up(int x)
{
T[x].Size=;
if(T[x].son[])
T[x].Size+=T[T[x].son[]].Size;
if(T[x].son[])
T[x].Size+=T[T[x].son[]].Size;
} void Insert(int &t,int val,int par=)
{
if(t==)
{
t=++tot;
T[t].init(val);
fa[t]=par;
Splay(tot,);
}
else
{
int cur=t;
if(val<T[t].val)Insert(T[t].son[],val,cur);
//else if(val==T[t].val)return ;
else Insert(T[t].son[],val,cur);
up(cur);
}
} int find(int t,int v)
{
if(t==)return ;
else if(T[t].val==v)
{
Splay(t,);
return t;
}
else if(v<T[t].val)return find(T[t].son[],v);
else return find(T[t].son[],v);
} ///Delete Root
void Delete()
{
if(!T[root].son[])
{
fa[T[root].son[]]=;
root=T[root].son[];
}
else
{
int cur=T[root].son[];
while(T[cur].son[])cur=T[cur].son[];
Splay(cur,root);
T[cur].son[]=T[root].son[];
root=cur,fa[cur]=,fa[T[root].son[]]=root;
up(root);
}
} int size()
{
return T[root].Size;
} ///找前驱
int pred(int t,int v)
{
if(t==)return v;
else
{
if(v<=T[t].val)return pred(T[t].son[],v);
else
{
int ans=pred(T[t].son[],v);
if(ans==v)
ans=T[t].val,Splay(t,);
return ans;
}
}
} ///找后继
int succ(int t,int v)
{
if(t==)return v;
else
{
if(v>=T[t].val)return succ(T[t].son[],v);
else
{
int ans=succ(T[t].son[],v);
if(ans==v)
ans=T[t].val,Splay(t,);
return ans;
}
}
} void Preorder( int t ){
if( !t ) return;
Preorder( T[t].son[] );
printf("%d " , T[t].val );
Preorder( T[t].son[] );
} void init()
{
T[].init(-INF);
tot=root=;
} }; Splay_Tree tree; int main()
{
int n,ans=;
scanf("%d",&n);
tree.init();
tree.Insert(tree.root,-INF);
tree.Insert(tree.root,INF);
scanf("%d",&ans);
tree.Insert(tree.root,ans);
for(int i=,x;i<n;i++)
{
scanf("%d",&x);
if(!tree.find(tree.root,x))
{
tree.Insert(tree.root,x);
ans+=min(x-tree.pred(tree.root,x),tree.succ(tree.root,x)-x);
}
}
printf("%d\n",ans);
return ;
}
再贴一个比较麻烦的题的代码FJUT2491
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int N=,INF=0x3f3f3f3f; struct Splay_Tree
{
struct Node
{
int val,Max,add,Size,son[];
bool rev;
void init(int _val)
{
val=Max=_val,Size=;
add=rev=son[]=son[]=;
}
} T[N];
int fa[N],root,tot,loc[N]; /*void pushDown(int x)
{
if(x==0)return ;
if(T[x].add)
{
if(T[x].son[0])
{
T[T[x].son[0]].val+=T[x].add;
T[T[x].son[0]].Max+=T[x].add;
T[T[x].son[0]].add+=T[x].add;
}
if(T[x].son[1])
{
T[T[x].son[1]].val+=T[x].add;
T[T[x].son[1]].Max+=T[x].add;
T[T[x].son[1]].add+=T[x].add;
}
T[x].add=0;
}
if(T[x].rev)
{
if(T[x].son[0])T[T[x].son[0]].rev^=1;
if(T[x].son[1])T[T[x].son[1]].rev^=1;
swap(T[x].son[0],T[x].son[1]);
T[x].rev=0;
}
}*/ /*void pushUp(int x)
{
T[x].Max=T[x].val,T[x].Size=1;
if(T[x].son[0])
{
T[x].Max=max(T[x].Max,T[T[x].son[0]].Max);
T[x].Size+=T[T[x].son[0]].Size;
}
if(T[x].son[1])
{
T[x].Max=max(T[x].Max,T[T[x].son[1]].Max);
T[x].Size+=T[T[x].son[1]].Size;
}
}*/ inline void up(int x)
{
T[x].Size=;
if(T[x].son[])
T[x].Size+=T[T[x].son[]].Size;
if(T[x].son[])
T[x].Size+=T[T[x].son[]].Size;
} void Rotate(int x,int kind)
{
int y=fa[x],z=fa[y];
T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;
T[x].son[kind]=y,fa[y]=x;
T[z].son[T[z].son[]==y]=x,fa[x]=z;
up(y);
} void Splay(int x,int goal)
{
if(x==goal)return ;
while(fa[x]!=goal)
{
int y=fa[x],z=fa[y];
int rx=T[y].son[]==x,ry=T[z].son[]==y;
if(z==goal)Rotate(x,rx);
else
{
if(rx==ry)Rotate(y,ry);
else Rotate(x,rx);
Rotate(x,ry);
}
}
up(x);
if(goal==)root=x;
} int Select(int pos)
{
pos--;
int u=root;
while(T[T[u].son[]].Size!=pos)
{
if(pos<T[T[u].son[]].Size)u=T[u].son[];
else
{
pos-=T[T[u].son[]].Size+;
u=T[u].son[];
}
}
return u;
} void update(int L,int R,int val)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
T[T[v].son[]].Max+=val;
T[T[v].son[]].val+=val;
T[T[v].son[]].add+=val;
} void Reverse(int L,int R)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
T[T[v].son[]].rev^=;
} int query(int L,int R)
{
int u=Select(L-),v=Select(R+);
Splay(u,);
Splay(v,u);
return T[T[v].son[]].Max;
} int build(int L,int R)
{
if(L>R)return ;
if(L==R)return L;
int mid=(L+R)>>,sL,sR;
T[mid].son[]=sL=build(L,mid-);
T[mid].son[]=sR=build(mid+,R);
fa[sL]=fa[sR]=mid;
up(mid);
return mid;
} void init(int n)
{
T[].init(-INF);
for(int i=,x;i<=n;i++)
{
scanf("%d",&x);
T[i].init(x),loc[x]=i;
}
root=build(,n),fa[root]=;
fa[]=,T[].son[]=root,T[].Size=;
} void Insert(int &t,int val,int par=)
{
if(t==)
{
t=++tot;
T[t].init(val);
fa[t]=par;
Splay(tot,);
}
else
{
int cur=t;
if(val<T[t].val)Insert(T[t].son[],val,cur);
//else if(val==T[t].val)return ;
else Insert(T[t].son[],val,cur);
up(cur);
}
} int find(int t,int v)
{
if(t==)return ;
else if(T[t].val==v)
{
Splay(t,);
return t;
}
else if(v<T[t].val)return find(T[t].son[],v);
else return find(T[t].son[],v);
} ///Delete Root
void Delete()
{
if(!T[root].son[])
{
fa[T[root].son[]]=;
root=T[root].son[];
}
else
{
int cur=T[root].son[];
while(T[cur].son[])cur=T[cur].son[];
Splay(cur,root);
T[cur].son[]=T[root].son[];
root=cur,fa[cur]=,fa[T[root].son[]]=root;
up(root);
}
} int size()
{
return T[root].Size;
} ///找前驱
int pred(int t,int v)
{
if(t==)return v;
else
{
if(v<=T[t].val)return pred(T[t].son[],v);
else
{
int ans=pred(T[t].son[],v);
if(ans==v)
ans=T[t].val,Splay(t,);
return ans;
}
}
} int pred(int t)
{
Splay(t,);
int u=T[t].son[];
if(u==)return fa[t];
while(T[u].son[])u=T[u].son[];
return u;
} ///找后继
int succ(int t,int v)
{
if(t==)return v;
else
{
if(v>=T[t].val)return succ(T[t].son[],v);
else
{
int ans=succ(T[t].son[],v);
if(ans==v)
ans=T[t].val,Splay(t,);
return ans;
}
}
} int succ(int t)
{
Splay(t,);
int u=T[t].son[];
if(u==)return fa[t];
while(T[u].son[])u=T[u].son[];
return u;
} void Preorder( int t ){
if( !t ) return;
Preorder( T[t].son[] );
if(T[t].son[]&&fa[T[t].son[]]!=t)
printf("!");
if(loc[T[t].val]!=t)
printf("?");
printf("%d " , T[t].val );
Preorder( T[t].son[] );
} void init()
{
T[].init(-INF);
tot=root=;
} void update(int x)
{
while(x!=)
up(x),x=fa[x];
} }; Splay_Tree tree; char s[]; int main()
{
int n,m;
scanf("%d%d",&n,&m);
tree.init(n);
int x,y,loc,locm,loch;
while(m--)
{
scanf("%s",s);
if(s[]=='T')
{
scanf("%d",&x);
loc=tree.loc[x];
locm=tree.Select();
if(locm==loc)
continue;
tree.Splay(loc,);
tree.Delete();
tree.T[locm].son[]=loc;
tree.fa[loc]=locm;
tree.T[loc].son[]=tree.T[loc].son[]=;
tree.update(loc);
}
else if(s[]=='B')
{
scanf("%d",&x);
loc=tree.loc[x];
locm=tree.Select(n);
if(locm==loc)
continue;
tree.Splay(loc,);
tree.Delete();
tree.T[locm].son[]=loc;
tree.fa[loc]=locm;
tree.T[loc].son[]=tree.T[loc].son[]=;
tree.update(loc);
}
else if(s[]=='I')
{
scanf("%d%d",&x,&y);
if(y==)
{
loc=tree.loc[x];
loch=tree.succ(loc);
swap(tree.T[loc].val,tree.T[loch].val);
swap(tree.loc[tree.T[loc].val],tree.loc[tree.T[loch].val]); }
else if(y==-)
{
loc=tree.loc[x];
loch=tree.pred(loc);
swap(tree.T[loc].val,tree.T[loch].val);
swap(tree.loc[tree.T[loc].val],tree.loc[tree.T[loch].val]);
}
}
else if(s[]=='A')
{
scanf("%d",&x);
loc=tree.loc[x];
tree.Splay(loc,);
printf("%d\n",tree.T[tree.T[loc].son[]].Size);
}
else if(s[]=='Q')
{
scanf("%d",&x);
printf("%d\n",tree.T[tree.Select(x)].val);
}
//tree.Preorder(tree.root);
//printf("\n");
}
return ;
}
平衡树(Splay)模板的更多相关文章
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)
解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...
- bzoj3224 普通平衡树 splay模板
题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #defi ...
- bzoj3224 普通平衡树(splay 模板)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11427 Solved: 4878[Submit][St ...
- [bzoj3224]Tyvj 1728 普通平衡树——splay模板
题目 你需要写一种数据结构支援以下操作. 插入元素. 删除元素. 查询元素的排名. 查询第k小的元素. 查询元素前趋. 查询元素后继. 题解 BBST裸题. 代码 #include <cstdi ...
- P3369 【模板】普通平衡树 (splay 模板)
题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多 ...
- 【BZOJ3224】Tyvj 1728 普通平衡树 Splay
Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...
- 文艺平衡树(splay模板)
题干:splay模板,要求维护区间反转. splay是一种码量小于treap,但支持排名,前驱后继等treap可求的东西,也支持区间反转的平衡树. 但是有两个坏处: 1.splay常数远远大于trea ...
- 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay
[阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
随机推荐
- 微信开发系列——微信订阅号前端开发利器:WeUI
前言:年前的两个星期,学习了下微信公众号的开发.后端基本能够基于盛派的第三方sdk能搞定大部分事宜.剩下的就是前端了,关于手机端的浏览器的兼容性,一直是博主的一块心病,因为博主一直专注于bootstr ...
- win10+anaconda+cuda配置dlib,使用GPU对dlib的深度学习算法进行加速(以人脸检测为例)
在计算机视觉和机器学习方向有一个特别好用但是比较低调的库,也就是dlib,与opencv相比其包含了很多最新的算法,尤其是深度学习方面的,因此很有必要学习一下.恰好最近换了一台笔记本,内含一块GTX1 ...
- js中boolean类型的理解
<html> <head> <script type="text/javascript"> var x="12"; aler ...
- uva437 DAG
直接套用DAG的思路就行. AC代码: #include<cstdio> #include<cstring> #include<algorithm> using n ...
- Activity的生命周期& 启动模式
1.Activity的生命周期 生命周期这个事情,是android工程师最基础的知识,所以今天要讲的是一些不一样的东西. 1.1 OnStart,OnResume,OnPause,OnStop 他们的 ...
- linux_group总结
group_name:passwd:GID:user_list 在/etc/group 中的每条记录分四个字段: 第一字段:用户组名称: 第二字段:用户组密码: 第三字段:GID 第四字段:用户列表, ...
- linux 存储技术 部署iSCSI NFS Multipath多路径
存储技术应用存储是根据不同的应用环境通过采取合理,安全,有效的方式将数据保存到某些介质上并能保证有效的访问另一方面,它是保证数据完整安全存放的方式或行为存储就是把这两方面结合起来,向客户提供一套数据存 ...
- mongodb副本集中其中一个节点宕机无法重启的问题
2-8日我还在家中的时候,被告知mongodb副本集中其中一个从节点因未知原因宕机,然后暂时负责代管的同事无论如何就是启动不起来. 当时mongodb的日志信息是这样的: 实际上这里这么长一串最重要的 ...
- 新手福音︱正则表达式小工具RegExr
由于之前在做NLP的内容,势必会接触正则表达式,但是呢,又觉得这个学不明白- 于是,这个工具还是蛮不错的,相当于在线正则速查+验证小工具,对于我这样的新手值得去玩玩. github:https://g ...
- ADS1.2中RO base与RW base
ARM映像文件 ARM中的各种源文件(包括汇编文件,C语言程序及C++程序等)经过ARM编译器编译后生成ELF(Executable and linking format)格式的目标文件.这些目标文件 ...