• 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
  • 相关阅读:
    申诉电信ADSL宽带限速
    回帖整理
    继续无题
    抛砖引玉,征集体会
    关于程序组织和组织技巧的学习
    周鸿祎行
    无题
    用此书为例讨论下软件思想的学习
    笔记
    方法论究竟为社区提供了什么
  • 原文地址:https://www.cnblogs.com/shangyu/p/3789609.html
Copyright © 2020-2023  润新知