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\n",

 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\n",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

 

 

 

你可能感兴趣的:(play)