平衡树Splay模板

  1 //cooode by xiaolang
  2 #include<cstdio>
  3 #include<iostream>
  4 #define N 100010
  5 using namespace std;
  6 int fa[N],ch[N][2],siz[N],cnt[N],data[N],root,nn,n,tot;
  7
  8 void pushup(int rt) {
  9     int l=ch[rt][0],r=ch[rt][1];
 10     siz[rt]=siz[l]+siz[r]+cnt[rt];
 11 }
 12 void rotate(int x,int &k) {
 13     int a=fa[x],b=fa[a],l,r;
 14     l= (ch[a][0]!=x);
 15     r= l^1;
 16     if(a==k) k=x;
 17     else
 18         ch[b][ch[b][1]==a]=x;
 19     fa[x]=b,fa[a]=x,fa[ch[x][r]]=a;
 20     ch[a][l]=ch[x][r],ch[x][r]=a;
 21     pushup(a);
 22 }
 23 void splay(int x,int &k) {
 24     int a,b;
 25     while(x!=k) {
 26         a=fa[x],b=fa[a];
 27         if(a!=k) {
 28             if((ch[a][0]==x)^(ch[b][0]==a))
 29                 rotate(x,k);
 30             else
 31                 rotate(a,k);
 32         }
 33         rotate(x,k);
 34         pushup(x);
 35     }
 36 }
 37 void ins(int &rt,int x) {
 38     if(rt==0) {
 39         rt=++nn;
 40         data[nn]=x;
 41         siz[nn]=cnt[nn]=1;
 42         return;
 43     }
 44     if(x==data[rt]) {
 45         cnt[rt]++;
 46         siz[rt]++;
 47         return;
 48     }
 49     if(x<data[rt]) {
 50         ins(ch[rt][0],x);
 51         fa[ch[rt][0]]=rt;
 52         pushup(rt);
 53     } else {
 54         ins(ch[rt][1],x);
 55         fa[ch[rt][1]]=rt;
 56         pushup(rt);
 57     }
 58 }
 59 int getmn(int rt) {
 60     while(ch[rt][0]) {
 61         rt=ch[rt][0];
 62     }
 63     if(!rt) return -1;
 64     return rt;
 65 }
 66 void del(int rt,int x) {
 67     if(data[rt]==x) {
 68         if(cnt[rt]>1) {
 69             cnt[rt]--;
 70             siz[rt]--;
 71         } else {
 72             splay(rt,root);
 73             int p=getmn(ch[rt][1]);
 74             if(p!=-1) {
 75                 splay(p,root);
 76                 fa[p]=0;
 77                 ch[p][0]=ch[rt][0];
 78                 fa[ch[rt][0]]=p;
 79                 pushup(p);
 80             } else {
 81                 root=ch[rt][0];
 82                 fa[ch[rt][0]]=0;
 83             }
 84         }
 85         return;
 86     }
 87     if(x<data[rt]) {
 88         del(ch[rt][0],x);
 89         pushup(rt);
 90     } else {
 91         del(ch[rt][1],x);
 92         pushup(rt);
 93     }
 94 }
 95 int getpre(int rt,int x) {
 96     int p=rt,ans;
 97     while(p) {
 98         if(x<=data[p]) {
 99             p=ch[p][0];
100         } else {
101             ans=p;
102             p=ch[p][1];
103         }
104     }
105     return ans;
106 }
107 int getsuc(int rt,int x) {
108     int p=rt,ans;
109     while(p) {
110         if(x>=data[p]) {
111             p=ch[p][1];
112         } else {
113             ans=p;
114             p=ch[p][0];
115         }
116     }
117     return ans;
118 }
119 int getk(int rt,int k) {
120     if(data[rt]==k) {
121         splay(rt,root);
122         if(ch[rt][0]==0) {
123             return 1;
124         } else {
125             return siz[ch[rt][0]]+1;
126         }
127     }
128     if(k<data[rt]) return getk(ch[rt][0],k);
129     else return getk(ch[rt][1],k);
130 }
131 int getkth(int rt,int k) {
132     int l=ch[rt][0];
133     if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return data[rt];
134     if(k<siz[l]+1) return getkth(ch[rt][0],k);
135     if(siz[l]+cnt[rt]<k) return getkth(ch[rt][1],k-(siz[l]+cnt[rt]));
136 }
137 int main() {
138     scanf("%d",&n);
139     while(n--) {
140         int opt,x;
141         scanf("%d%d",&opt,&x);
142         if(opt==1) {
143             tot++;
144             ins(root,x);
145         }
146         if(opt==2) {
147             tot--;
148             del(root,x);
149         }
150         if(opt==3) {
151             printf("%d\n",getk(root,x));
152         }
153         if(opt==4) {
154             printf("%d\n",getkth(root,x));
155         }
156         if(opt==5) {
157             printf("%d\n",data[getpre(root,x)]);
158         }
159         if(opt==6) {
160             printf("%d\n",data[getsuc(root,x)]);
161         }
162     }
163     return 0;
164 }
时间: 2024-11-13 00:26:10

平衡树Splay模板的相关文章

bzoj3224 普通平衡树(splay 模板)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11427  Solved: 4878[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

bzoj3224 普通平衡树 splay模板

题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int root,N=0,n,p,q; int fa[100001],c[100001][2],size[100001],sp[100001]; void

【BZOJ3224】Tyvj 1728 普通平衡树 Splay

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) Output 对于操作3,4,5,6每行输

洛谷 P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是 (1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1≤l≤r≤n 输出格式: 输出一行n个数字,表示原始序列经过m次变换后的结果

文艺平衡树(splay模板)

题干:splay模板,要求维护区间反转. splay是一种码量小于treap,但支持排名,前驱后继等treap可求的东西,也支持区间反转的平衡树. 但是有两个坏处: 1.splay常数远远大于treap以及stl中的set. 2.没有可持久化splay,但有可持久化treap. 下面是代码: 1.pushup以及pushdown pushup用于维护某点所在子树大小. void pushup(int u) { tr[u].siz = tr[tr[u].ch[0]].siz + tr[tr[u].

[bzoj3223]文艺平衡树(splay区间反转模板)

解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int N = 100005; int ch[N][2],par[N],val[N],cnt[

bzoj1500(妥妥的splay模板题)

1500: [NOI2005]维修数列 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 6366  Solved: 1910 [Submit][Status] Description Input 输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目.第2行包含N个数字,描述初始时的数列.以下M行,每行一条命令,格式参见问题描述中的表格. Output 对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次

splay模板

先贴一份不怎么完善的模板,等刷一些题目熟悉之后再来完善.代码参考自kuangbin及cxlove两位大神. splay的基本功能 题目:维护一个数列,支持以下几种操作: 1. 插入:在当前数列第posi 个数字后面插入tot 个数字:若在数列首位插入,则posi 为0. 2. 删除:从当前数列第posi 个数字开始连续删除tot 个数字. 3. 修改:从当前数列第posi 个数字开始连续tot 个数字统一修改为c . 4. 翻转:取出从当前数列第posi 个数字开始的tot 个数字,翻转后放入原

bzoj 1588 splay模板题

用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 33333 6 #define inf 0x3f3f3f3f 7 #define lc(x) ch[(x)][0] 8 #define rc(x) ch[(x)