splay模板

先贴一份不怎么完善的模板,等刷一些题目熟悉之后再来完善。代码参考自kuangbin及cxlove两位大神。

splay的基本功能

题目:维护一个数列,支持以下几种操作:

1. 插入:在当前数列第posi 个数字后面插入tot 个数字;若在数列首位插入,则posi 为0。

2. 删除:从当前数列第posi 个数字开始连续删除tot 个数字。

3. 修改:从当前数列第posi 个数字开始连续tot 个数字统一修改为c 。

4. 翻转:取出从当前数列第posi 个数字开始的tot 个数字,翻转后放入原来的位置。

5. 求和:计算从当前数列第posi 个数字开始连续tot 个数字的和并输出。

6. 求和最大子序列:求出当前数列中和最大的一段子序列,并输出最大和。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 using namespace std;
 11 #define N 200010
 12 #define LL __int64
 13 #define INF 0xfffffff
 14 #define key_value ch[ch[root][1]][0]
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 int pre[N],s[N],size[N];
 19 int ch[N][2],a[N],val[N],key[N];
 20 int root,n,tot;
 21 void dfs(int x)
 22 {
 23     if(x)
 24     {
 25         dfs(ch[x][0]);
 26         printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d add=%2d sum=%I64d\n",
 27                x,ch[x][0],ch[x][1],pre[x],size[x],key[x],add[x],s[x]);
 28         dfs(ch[x][1]);
 29     }
 30 }
 31 void debug()
 32 {
 33     printf("root:%d\n",root);
 34     dfs(root);
 35 }
 36 //以上用于debug
 37 void newnode(int &x,int k,int fa)//新建一结点
 38 {
 39     x = ++tot;
 40     ch[x][0]=ch[x][1] = 0;
 41     pre[x] = fa;
 42     size[x] = 1;
 43     s[x] = k;
 44     val[x] = k;
 45 }
 46 void pushup(int w)//由儿子更新其父亲
 47 {
 48     size[w] = size[ch[w][0]]+size[ch[w][1]]+1;
 49     s[w] = max(max(s[ch[w][0]],s[ch[w][1]]),val[w]);
 50 }
 51 void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
 52 {
 53     int y = pre[r];
 54     ch[y][!kind] = ch[r][kind];
 55     pre[ch[r][kind]] = y;
 56     if(pre[y])
 57     {
 58         ch[pre[y]][ch[pre[y]][1]==y] = r;
 59     }
 60     pre[r] = pre[y];
 61     ch[r][kind] = y;
 62     pre[y] = r;
 63     pushup(y);
 64 }
 65 void splay(int r,int goal)//将r结点旋至goal下
 66 {
 67     while(pre[r]!=goal)
 68     {
 69        if(pre[pre[r]]==goal)
 70         {
 71              rotate(r,ch[pre[r]][0]==r);
 72         }
 73         else
 74         {
 75             int y = pre[r];
 76             int kind = (ch[pre[y]][0]==y);
 77             if(ch[y][kind]==r)
 78             {
 79                 rotate(r,!kind);
 80                 rotate(r,kind);
 81             }
 82             else
 83             {
 84                 rotate(y,kind);
 85                 rotate(r,kind);
 86             }
 87         }
 88     }
 89     pushup(r);
 90     if(goal==0) root = r;
 91 }
 92 int get_k(int k)//得到第k个的结点
 93 {
 94     int r = root;
 95     while(size[ch[r][0]]!=k)
 96     {
 97         if(size[ch[r][0]]>k)
 98         r = ch[r][0];
 99         else
100         {
101             k-=(size[ch[r][0]]+1);//根据左右结点的数量来确定第k个节点在哪里
102             r = ch[r][1];
103         }
104     }
105     return r;
106 }
107 int query(int l,int r)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
108 {                       //则l-r就变成了根的右儿子的左儿子
109     splay(get_k(l-1),0);
110     splay(get_k(r+1),root);
111     return s[key_value];
112 }
113 void update(int l,int r,int k)//区间更新,类似于询问
114 {
115     splay(get_k(l-1),0);
116     splay(get_k(r+1),root);
117     val[key_value] = k;
118     s[key_value] = k;
119     pushup(ch[root][1]);
120     pushup(root);
121 }
122 void update(int l,int r,int k)//单点更新,将所求点旋至根
123 {
124     int kk = get_k(l);
125     val[kk] = k;
126     splay(kk,0);
127 }
128 void build(int &w,int l,int r,int fa)//递归建树
129 {
130     if(l>r) return ;
131     int m = (l+r)>>1;
132     newnode(w,a[m],fa);
133     build(ch[w][0],l,m-1,w);
134     build(ch[w][1],m+1,r,w);
135     pushup(w);
136 }
137 void init()//初始化操作,增加一个最小和最大值结点,防止越界
138 {
139     int i;
140     for(i = 0 ;i < n ;i++)
141     scanf("%d",&a[i]);
142     ch[0][0] = ch[0][1] = pre[0] = size[0] = s[0] = 0;
143     root = tot =0;
144     newnode(root,-1,0);
145     newnode(ch[root][1],-1,root);
146     size[root] = 2;
147     build(key_value,0,n-1,ch[root][1]);
148     pushup(ch[root][1]);
149     pushup(root);
150 }

splay模板,布布扣,bubuko.com

时间: 2024-12-27 08:50:05

splay模板的相关文章

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)

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操作,向输出文件依次

COJ 1002 WZJ的数据结构(二)(splay模板)

我的LCC,LCT,Splay格式终于统一起来了... 另外..这个形式的Splay是标准的Splay(怎么鉴别呢?看Splay函数是否只传了一个变量node就行),刘汝佳小白书的Splay写的真是不想吐槽了,局限性太大,别学... 好了我要去写维修数列了..... 标准Splay模板: 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #inc

BZOJ1588 [HNOI2002]营业额统计 splay模板

1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 16189  Solved: 6482 [Submit][Status][Discuss] Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额.分析营业情况是一项相当复杂的工作.由于节假日,大减价或者

文艺平衡树(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].

伸展树 Splay 模板

学习Splay的时候参考了很多不同的资料,然而参考资料太杂的后果就是模板调出来一直都有问题,尤其是最后发现网上找的各种资料均有不同程度的错误. 好在啃了几天之后终于算是啃下来了. Splay也算是平衡树的一种,但是跟AVL树.SBT不同的是,Splay并不是一直保持严格的平衡,因此在速度上可能要慢一些,但是统计学上仍能保证Splay具有O(logn)的均摊复杂度. Splay原生不需要附加任何空间,它的先天优势是其特有的Splay操作可以非常灵活地改变整棵树的结构形态,完成一般线段树.平衡树做不

POJ 3481 splay模板

最后撸一发splay. 之前用treap撸的,现在splay也找到感觉了,果然不同凡响,两者之间差别与精妙之处各有其精髓! 真心赞一个! POJ平衡树的题目还是比较少,只能挑之前做过的捏一捏.但是收获很多,这一天做的题都是有一定普遍性的. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> #include

Bzoj 1251: 序列终结者 (Splay 模板题)

题面(太裸太裸,不看也罢) 就是维护一个区间加,区间翻转和区间最大值. 贴一个风格以后可以一直用 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 100000 6 #define XX getchar() 7 using namespace std; 8 int ch[N][2],fa[N],rev[N],ad[N],b

Splay模板(序列终结者)

我只是一个存模板的,详细的请看这里http://blog.csdn.net/whai362/article/details/47298133 1 #include <cstdio> 2 #include <cstring> 3 #include <cctype> 4 #include <cmath> 5 #include <set> 6 #include <map> 7 #include <list> 8 #include