Treap 模板
感觉平衡树也没有以前想的那么玄乎,(其实set超好用的),非旋式Treap挺好理解,和可并堆,二叉搜索树有很大联系
推荐博客:http://memphis.is-programmer.com/posts/46317.html
模板也是摘自这位dalao的
#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define dep(i,x,y) for(int i=x;i>=y;--i) struct Treap{
Treap *l,*r;
int fix,key,size;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(){} inline void updata(){
size=+(l?l->size:)+(r?r->size:);
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针 Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
} Treap *Build(int *a){//建造操作
static Treap *stack[maxn],*x,*last;
int p=;
rep(i,,a[]){
x=new Treap(a[i]);
last=NULL;
while(p && stack[p]->fix>x->fix){
stack[p]->updata();
last=stack[p];
stack[p--]=NULL;
}
if(p) stack[p]->r=x;
x->l=last;
stack[++p]=x;
}
while(p) stack[p--]->updata();
return stack[];
} int Findkth(int k){//查找第K小
Droot x=Split(root,k-);
Droot y=Split(x.second,);
Treap *ans=y.first;
root=Merge(Merge(x.first,ans),y.second);
return ans->key;
} int Getkth(Treap *x,int v){//询问一个数是第几大
if(!x)return ;
return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+;
} void Insert(int v){//插入操作
int k=Getkth(root,v);
Droot x=Split(root,k);
Treap *n=new Treap(v);
root=Merge(Merge(x.first,n),x.second);
} void Delete(int k){//删除操作
Droot x=Split(root,k-);
Droot y=Split(x.second,);
root=Merge(x.first,y.second);
} int a[maxn],M,x,y; int main(){
scanf("%d",a);
rep(i,,a[]) scanf("%d",a+i);
sort(a+,a++a[]);
root=Build(a);
scanf("%d",&M);
while(M--){
char ch=getchar();
while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
scanf("%d",&x);
if(ch=='Q') printf("%d\n",Findkth(x));
if(ch=='A') Insert(x);
if(ch=='D') Delete(x);
}
}
改了一下之后就A了文艺平衡树
#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define dep(i,x,y) for(int i=x;i>=y;--i)
int n;
struct Treap{
Treap *l,*r;
int fix,key,size;
bool fg;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(){} inline void updata(){
size=+(l?l->size:)+(r?r->size:);
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针
void pushdown(Treap *x){
if(!x->fg)return;
x->fg=;
swap(x->l,x->r);
if( x->l ) x->l->fg^=;
if( x->r ) x->r->fg^=;
}
Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
pushdown(A);pushdown(B);
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
pushdown(x);
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
}
Treap *build(int L,int R){
if(L>R)return NULL;
int mid=(L+R)>>,key=mid-;
Treap *x =new Treap(key);
x->l = build(L,mid-);
x->r = build(mid+,R);
x->updata();
return x;
}
Treap *Build(int *a){//建造操作
static Treap *stack[maxn],*x,*last;
int p=;
rep(i,,a[]){
x=new Treap(a[i]);
last=NULL;
while(p && stack[p]->fix>x->fix){
stack[p]->updata();
last=stack[p];
stack[p--]=NULL;
}
if(p) stack[p]->r=x;
x->l=last;
stack[++p]=x;
}
while(p) stack[p--]->updata();
return stack[];
} void order(Treap *x){
if( x == NULL ) return;
pushdown(x);
order(x->l);
if(x->key >= && x->key<=n)printf("%d ",x->key);
order(x->r);
}
void rev(int L,int R){
Droot tmp1=Split(root,R+);
Droot tmp2=Split(tmp1.first,L);
tmp2.second->fg^=;
root = NULL;
root = Merge(tmp2.first,tmp2.second);
root = Merge(root,tmp1.second);
}
//int Findkth(int k){//查找第K小
// Droot x=Split(root,k-1);
// Droot y=Split(x.second,1);
// Treap *ans=y.first;
// root=Merge(Merge(x.first,ans),y.second);
// return ans->key;
//} //int Getkth(Treap *x,int v){//询问一个数是第几大
// if(!x)return 0;
// return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1;
//} //void Insert(int v){//插入操作
// int k=Getkth(root,v);
// Droot x=Split(root,k);
// Treap *n=new Treap(v);
// root=Merge(Merge(x.first,n),x.second);
//} //void Delete(int k){//删除操作
// Droot x=Split(root,k-1);
// Droot y=Split(x.second,1);
// root=Merge(x.first,y.second);
//} //int a[maxn],M,x,y;
int M;
int main(){
//scanf("%d",a);
//rep(i,1,a[0]) scanf("%d",a+i);
//sort(a+1,a+1+a[0]);
//root=Build(a);
scanf("%d",&n);
scanf("%d",&M);
root=build(,n+);
int L,R;
while(M--){
// char ch=getchar();
// while(ch!='Q' && ch!='A' && ch!='D') ch=getchar();
// scanf("%d",&x);
// if(ch=='Q') printf("%d\n",Findkth(x));
// if(ch=='A') Insert(x);
// if(ch=='D') Delete(x);
scanf("%d%d",&L,&R);
rev(L,R);
}
order(root);
}
再粘一个非指针版的我敬爱的学长szb写的,浙大一本爷
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define mp make_pair
typedef pair<int,int> par;
const int N=;
const int inf=1e9;
int n,root,cnt;
int l[N],r[N],key[N],rnd[N],size[N];
int readin() {
int x=,f=; char ch=getchar();
while(ch>''||ch<'') {if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
return x*f;
}
void update(int x) {
size[x]=size[l[x]]+size[r[x]]+;
return;
}
int merge(int x,int y) {
if (!x||!y)
return x+y;
if (rnd[x]<rnd[y]) {
r[x]=merge(r[x],y);
update(x); return x;
}
else {
l[y]=merge(x,l[y]);
update(y); return y;
}
}
par split(int x,int k) {
if (k==)
return mp(,x);
int ls=l[x],rs=r[x];
if (k<=size[l[x]]) {
par t=split(l[x],k);
l[x]=t.second; update(x);
return mp(t.first,x);
}
else if (k==size[l[x]]+) {
r[x]=; update(x);
return mp(x,rs);
}
else {
par t=split(rs,k-(size[l[x]]+));
r[x]=t.first; update(x);
return mp(x,t.second);
}
}
int query_rank(int x,int k) {
int ans=,t=inf;
while(x) {
if (k==key[x]) t=min(t,ans+size[l[x]]+);
if (k>key[x]) ans+=(size[l[x]]+),x=r[x];
else x=l[x];
}
return t==inf?ans:t;
}
void insert(int x) {
int k=query_rank(root,x);
par t=split(root,k);
key[++cnt]=x,rnd[cnt]=rand(),size[cnt]=;
root=merge(t.first,cnt);
root=merge(root,t.second);
return;
}
void del(int x) {
int k=query_rank(root,x);
par t1=split(root,k);
par t2=split(t1.first,k-);
root=merge(t2.first,t1.second);
return;
}
int query_num(int x,int k) {
while() {
if (k==size[l[x]]+) return key[x];
if (k<=size[l[x]]) x=l[x];
else k-=(size[l[x]]+),x=r[x];
}
}
int query_pre(int x,int k) {
int ans=-inf;
while(x) {
if (key[x]<k)
ans=max(ans,key[x]),x=r[x];
else
x=l[x];
}
return ans;
}
int query_sub(int x,int k) {
int ans=inf;
while(x) {
if (key[x]>k)
ans=min(ans,key[x]),x=l[x];
else
x=r[x];
}
return ans;
}
int main() {
int opt,x;
n=readin();
for (int i=;i<=n;i++) {
opt=readin(),x=readin();
if (opt==) insert(x);
else if (opt==) del(x);
else if (opt==) printf("%d\n",query_rank(root,x));
else if (opt==) printf("%d\n",query_num(root,x));
else if (opt==) printf("%d\n",query_pre(root,x));
else printf("%d\n",query_sub(root,x));
}
return ;
}
序列终结者 ,调了好久发现区间截取错了那我咋A的文艺平衡树啊???啊~好像是那个程序建树的时候整个往后串了一位
#include<bits/stdc++.h>
using namespace std;
#define maxn 2000005
int n;
#define inf 1000000000
struct Treap{
Treap *l,*r;
int fix,key,size,mx,add;
bool fg;
Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(),mx(),fg(),add(){}
void addv(int w){mx+=w;add+=w;key+=w;}
inline void updata(){
size=+(l?l->size:)+(r?r->size:);
mx=max(key,max((l?l->mx:-inf),(r?r->mx:-inf)));
}
}*root;
typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:;}//这样求size可以防止访问空指针
void pushdown(Treap *x){
if(x->fg){
x->fg=;
swap(x->l,x->r);
if( x->l ) x->l->fg^=;
if( x->r ) x->r->fg^=;}
if(x->add){
if( x->l ) x->l->addv(x->add);
if( x->r ) x->r->addv(x->add);
x->add=;
}
}
Treap *Merge(Treap *A,Treap *B){//合并操作
if(!A)return B;
if(!B)return A;
pushdown(A);pushdown(B);
if(A->fix<B->fix){
A->r=Merge(A->r,B);
A->updata();
return A;
}
else{
B->l=Merge(A,B->l);
B->updata();
return B;
}
} Droot Split(Treap *x,int k){//拆分操作
if(!x)return Droot(NULL,NULL);
Droot y;
pushdown(x);
if(Size(x->l)>=k){
y=Split(x->l,k);
x->l=y.second;
x->updata();
y.second=x;
}
else{
y=Split(x->r,k-Size(x->l)-);
x->r=y.first;
x->updata();
y.first=x;
}
return y;
} void rev(int L,int R){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
tmp2.second->fg^=;
root = Merge( Merge(tmp2.first,tmp2.second),tmp1.second);
}
void up(int L,int R,int v){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
tmp2.second->addv(v);
root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
}
int query(int L,int R){
Droot tmp1=Split(root,R);
Droot tmp2=Split(tmp1.first,L-);
int ret=tmp2.second->mx;
root = Merge(Merge(tmp2.first,tmp2.second),tmp1.second);
return ret;
}
int M;
int main(){
scanf("%d",&n);
scanf("%d",&M);
for(int i=;i<=n;i++){
Treap *a=new Treap();
root=Merge(root,a);
}
int L,R;
int f,v;
while(M--){
scanf("%d",&f);
if(f==){ scanf("%d%d%d",&L,&R,&v);
up(L,R,v);}
else if(f==){
scanf("%d%d",&L,&R); rev(L,R);
}
else {
scanf("%d%d",&L,&R);
printf("%d\n",query(L,R));
}
} }
Treap 模板的更多相关文章
- BZOJ 1588: Treap 模板
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 12171 Solved: 4352 Description ...
- [luogu3369]普通平衡树(treap模板)
解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...
- Treap 模板 poj1442&hdu4557
原理可以看hihocoder上面的讲解,很清楚,不多说了. 模板抄lrj训练指南上面的. /** Treap 实现 名次树 功能: 1.找到排名为k的元素 2.值为x的元素的名次 初始化:Node* ...
- 平衡树Treap模板与原理
这次我们来讲一讲Treap(splay以后再更) 平衡树是一种排序二叉树(或二叉搜索树),所以排序二叉树可以迅速地判断两个值的大小,当然操作肯定不止那么多(不然我们还学什么). 而平衡树在排序二叉树的 ...
- POJ1442-查询第K大-Treap模板题
模板题,以后要学splay,大概看一下treap就好了. #include <cstdio> #include <algorithm> #include <cstring ...
- 【Treap模板详细注释】BZOJ3224-普通平衡树
模板题:D错因见注释 #include<iostream> #include<cstdio> #include<cstring> #include<algor ...
- 非旋treap模板
bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...
- codevs 4543 treap 模板
type rec=record lc,rc,v,rnd,size,w,fa:longint; end; var n,root,tot,ans,opt,x,i,po:longint; tr:array[ ...
- Treap模板
平衡树总是有用的,set由于过度封装没有办法实现找比x小的元素有多少个,这就显得很不方便了,所以封装了个Treap,万一以后用的着呢- -01 #pragma warning(disable:4996 ...
随机推荐
- Spark-源码-TaskScheduler初始化过程, ClientActor向Master发送注册任务信息过程
Spark版本 1.3 Spark源码 Spark.createTaskScheduler TaskScheduler初始化过程 1.// SparkContext中 /** * Create a t ...
- Centos7 搭建 hadoop3.1.1 集群教程
配置环境要求: Centos7 jdk 8 Vmware 14 pro hadoop 3.1.1 Hadoop下载 安装4台虚拟机,如图所示 克隆之后需要更改网卡选项,ip,mac地址,uuid 重启 ...
- AES128加密-S盒和逆S盒构造推导及代码实现
文档引用了<密码编码学与网络安全--原理和实践>里边的推导过程,如有不妥,请与我联系修改. 文档<FIPS 197>高级加密标准AES,里边有个S盒构造,涉及到了数论和有限域的 ...
- 分布式redis一些小结
本文围绕以下几点进行阐述: 为什么使用 Redis 使用 Redis 有什么缺点 单线程的 Redis 为什么这么快 Redis 的数据类型,以及每种数据类型的使用场景 Redis 的过期策略以及内存 ...
- WPF 构建无外观(Lookless)控件
原文:WPF 构建无外观(Lookless)控件 构建一个用户可以使用Template属性设置外观的WPF控件需要以下几步 1.继承自System.Windows.Controls.Control 2 ...
- SPOJ SUBLEX
SUBLEX - Lexicographical Substring Search 链接 题意 求第k小的子串.相同的算一个. 分析 建立后缀自动机,在后缀自动机上从一个点经过trans,到另一个点, ...
- valgrind检查still reachable情况
valgrind --leak-check=yes检查bufr编解码程序运行时提示still reachable: 568 bytes in 1 blocks,如下图示: 于是怀疑有内存泄漏,难道是m ...
- Java的HashMap和HashTable
Java的HashMap和HashTable 1. HashMap 1) hashmap的数据结构 Hashmap是一个数组和链表的结合体(在数据结构称“链表散列“),如下图示: 当我们往hashm ...
- .netcore centos环境搭建实战
步骤 1. 安装VMware Workstation 下载地址:https://my.vmware.com/cn/web/vmware/info/slug/desktop_end_user_compu ...
- Leetcode代码补全——二叉树
在刷leetcode的过程中发现,在原网页输入答案是不需要自己构筑树和链表的,虽然便于直接思考算法,但是久而久之类似过于依赖编辑器,反而不知道如何创建树和链表,因此总结了该网页省略的部分,以其中题为例 ...