splay模板

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

splay的基本功能

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

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

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

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

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

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

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

  1 struct splay_tree
  2 {
  3     int pre[N],size[N],vv[N];
  4     int ch[N][2];
  5     int root,n,tot,num,tot1;
  6     int s[N],sta[N],key[N];
  7     void dfs(int x)
  8     {
  9         if(x)
 10         {
 11             dfs(ch[x][0]);
 12             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d s=%d vv=%d
",
 13                    x,ch[x][0],ch[x][1],pre[x],size[x],key[x],s[x],vv[x]);
 14             dfs(ch[x][1]);
 15         }
 16     }
 17     void debug()
 18     {
 19         printf("root:%d
",root);
 20         dfs(root);
 21     }
 22 //以上用于debug*/
 23     void newnode(int &x,int v,int len,int fa)//新建一结点
 24     {
 25         x = ++tot;
 26         ch[x][0]=ch[x][1] = 0;
 27         pre[x] = fa;
 28         size[x] = 1;
 29         s[x] = len;
 30         vv[x] = len;
 31         key[x] = v;
 32         po[f[v]] = x;
 33     }
 34     void pushup(int w)//由儿子更新其父亲
 35     {
 36         size[w] = size[ch[w][0]]+size[ch[w][1]]+1;
 37         s[w] = s[ch[w][0]]+s[ch[w][1]]+vv[w];
 38     }
 39     void rotate(int r,int kind)//旋转操作,根据kind进行左旋和右旋
 40     {
 41         int y = pre[r];
 42         ch[y][!kind] = ch[r][kind];
 43         pre[ch[r][kind]] = y;
 44         if(pre[y])
 45         {
 46             ch[pre[y]][ch[pre[y]][1]==y] = r;
 47         }
 48         pre[r] = pre[y];
 49         ch[r][kind] = y;
 50         pre[y] = r;
 51         pushup(y);
 52         pushup(r);
 53     }
 54     void splay(int r,int goal)//将r结点旋至goal下
 55     {
 56         while(pre[r]!=goal)
 57         {
 58             if(pre[pre[r]]==goal)
 59             {
 60                 rotate(r,ch[pre[r]][0]==r);
 61             }
 62             else
 63             {
 64                 int y = pre[r];
 65                 int kind = (ch[pre[y]][0]==y);
 66                 if(ch[y][kind]==r)
 67                 {
 68                     rotate(r,!kind);
 69                     rotate(r,kind);
 70                 }
 71                 else
 72                 {
 73                     rotate(y,kind);
 74                     rotate(r,kind);
 75                 }
 76             }
 77         }
 78         pushup(r);
 79         if(goal==0) root = r;
 80     }
 81     int get_k(int k)//得到第k个的结点
 82     {
 83         int r = root;
 84         while(size[ch[r][0]]+1!=k)
 85         {
 86             if(size[ch[r][0]]>=k)
 87                 r = ch[r][0];
 88             else
 89             {
 90                 k-=(size[ch[r][0]]+1);//根据左右结点的数量来确定第k个节点在哪里
 91                 r = ch[r][1];
 92             }
 93         }
 94         pushup(r);
 95         return r;
 96     }
 97     void add(int v)//添加一个结点 位置自己修改 这里为第一个
 98     {
 99         splay(get_k(1),0);
100         splay(get_k(2),root);
101         int r = ch[root][1];
102         newnode(ch[r][0],v,1,r);
103         pushup(r);
104         pushup(root);
105     }
106     void updelete(int k,int r)//删除第r个结点
107     {
108         splay(get_k(r),0);
109         splay(get_k(r+2),root);
110         //int ll = vv[key_value];
111         key_value = 0;
112         /*if(ll>1)
113         newnode(key_value,k-1,ll-1,ch[root][1]);*/
114         pushup(ch[root][1]);
115         pushup(root);
116     }
117     void update(int l,int r) //更新区间信息
118     {
119         
120     }
121     int query(int l,int r)//询问l,r区间,将第l-1个结点旋自根,第r+1个结点旋自根的有儿子,
122     {
123         //则l-r就变成了根的右儿子的左儿子
124         splay(get_k(l),0);
125         splay(get_k(r+2),0);
126         return s[key_value];
127     }
128     int find(int p,int x)//找到离散化后的第p个数
129     {
130         int l = ch[x][0];
131         int r = ch[x][1];
132         if(!l&&!r)
133         {
134             return key[x]-(vv[x]-p);
135         }
136         if(s[l]>=p)
137         return find(p,l);
138         else if(s[l]+vv[x]>=p)
139         return key[x]-(vv[x]-(p-s[l]));
140         else return find(p-s[l]-vv[x],r);
141     }
142     void build(int &x,int l,int r,int fa)
143     {
144         int m = (l+r)>>1;
145         if(l>r) return ;
146         newnode(x,va[m],len[m],fa);
147         build(ch[x][0],l,m-1,x);
148         build(ch[x][1],m+1,r,x);
149         pushup(x);
150     }
151     void init(int o)
152     {
153         size[0] = ch[0][0] = ch[0][1] = s[0] = key[0] = vv[0] = 0;
154         root = tot = 0;
155         newnode(root,0,0,0);
156         newnode(ch[root][1],0,0,root);
157         build(ch[ch[root][1]][0],1,o,ch[root][1]);
158         size[root] = 2;
159         pushup(ch[root][1]);
160         pushup(root);
161     }
162 }SP;
View Code
原文地址:https://www.cnblogs.com/shangyu/p/3789609.html