• 可持久化平衡树 = 可持久化线段树 + 平衡线段树


    可持久化平衡树

    根据可持久化的基本思想可以得到: 一个数据结构可持久化, 可以存在一个儿子有多个父亲, 但是不允许一个父亲在同一位置 (如左儿子) 有多个儿子. 所以平衡树可持久化的基本条件是节点只记录儿子节点, 不记录父亲节点.

    选择哪种平衡树用来持久化就是可持久化平衡树的第一步. 因为不能记录父亲, Treap 和 Splay 就已经被卡掉了. 然后查找一下我的知识储备, 还剩下替罪羊和 WBLT. 这两者都不记录父亲, 但是 WBLT 又名平衡线段树, 因为它的结构非常类似于线段树, 我们早已掌握了可持久化线段树, 那么可持久化平衡线段树树也变得简单多了.

    因为儿子被多个父亲共用, 所以过程中要注意, 只能修改新建的节点的信息. 新建的节点指的是没有被共用, 只有一个父亲的节点.

    代码逻辑还是比较清晰的, 唯一的不足是会有节点被浪费, 也就是这个节点不存在却需要为它开内存的情况, 所以空间最多的点 (470MB), 不过卡着过了.

    钻了个空子, 用平衡线段树持久化了一下, 一般只要会可持久化线段树和平衡线段树的都会写.

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <vector>
    #define Wild_Donkey 0
    using namespace std;
    inline unsigned RD() {
      unsigned intmp(0);
      char rdch(getchar());
      while (rdch < '0' || rdch > '9') rdch = getchar();
      while (rdch >= '0' && rdch <= '9') {
        intmp = (intmp << 3) + (intmp << 1) + rdch - '0';
        rdch = getchar();
      }
      return intmp;
    }
    inline int RDsg() {
      int rdtp(0), rdsg(1);
      char rdch(getchar());
      while ((rdch < '0' || rdch > '9') && (rdch != '-')) rdch = getchar();
      if (rdch == '-') {
        rdsg = -1;
        rdch = getchar();
      }
      while (rdch >= '0' && rdch <= '9') {
        rdtp = (rdtp << 3) + (rdtp << 1) + rdch - '0';
        rdch = getchar();
      }
      return rdtp * rdsg;
    }
    unsigned m, n, A, B, C, t, Ans(0);
    int D;
    struct Node {
      Node *LS, *RS;
      unsigned Cnt, Size;
      int Val, InVal;
    }N[20000005], *Ver[500005], *CntN(N);
    inline void Rotate(Node *x) {
      if(x->Size > 4) {
        register Node *Tmp(++CntN);
        if(x->LS->Size * 3 < x->RS->Size) {
          Tmp->LS = x->LS;
          Tmp->RS = x->RS->LS;
          x->RS = x->RS->RS;
          x->LS = Tmp;
          Tmp->InVal = Tmp->LS->InVal;
          Tmp->Val = Tmp->RS->Val;
          Tmp->Size = Tmp->LS->Size + Tmp->RS->Size;
          Tmp->Cnt = Tmp->LS->Cnt + Tmp->RS->Cnt;
          return;
        }
        if(x->RS->Size * 3 < x->LS->Size) {
          Tmp->RS = x->RS;
          Tmp->LS = x->LS->RS;
          x->LS = x->LS->LS;
          x->RS = Tmp;
          Tmp->InVal = Tmp->LS->InVal;
          Tmp->Val = Tmp->RS->Val; 
          Tmp->Size = Tmp->LS->Size + Tmp->RS->Size;
          Tmp->Cnt = Tmp->LS->Cnt + Tmp->RS->Cnt;
          return;
        }
      }
    }
    void Insert(Node *x, Node *y) {
      y->Cnt = x->Cnt + 1;
      if(x->Val == x->InVal) {
        if(x->Val ^ D) {
          y->Size = 2;
          y->LS = ++CntN, y->RS = ++CntN;
          if(x->Val < D) {
            y->LS->InVal = y->LS->Val = x->Val;
            y->RS->InVal = y->RS->Val = D;
            y->RS->Cnt = 1;
            y->LS->Cnt = x->Cnt;
            y->Val = D;
            y->InVal = x->InVal;
          } else {
            y->RS->InVal = y->RS->Val = x->Val;
            y->LS->InVal = y->LS->Val = D;
            y->LS->Cnt = 1;
            y->RS->Cnt = x->Cnt;
            y->InVal = D;
            y->Val = x->Val;
          }
          y->LS->Size = y->RS->Size = 1;
        } else {
          y->Val = y->InVal = D, y->Size = 1;
        }
        return;
      }
      if(D <= x->LS->Val) {
        y->RS = x->RS;
        Insert(x->LS, y->LS = ++CntN);
        y->InVal = y->LS->InVal;
        y->Val = x->Val;
      } else {
        y->LS = x->LS;
        Insert(x->RS, y->RS = ++CntN);
        y->Val = y->RS->Val;
        y->InVal = x->InVal;
      }
      y->Size = y->LS->Size + y->RS->Size;
      Rotate(y);
    }
    Node *Delete (Node *x, Node *y)  {
      if(x->Val == x->InVal) {
        y->Cnt = x->Cnt;
        if(x->Val == D) {
          --(y->Cnt);
        }
        if(y->Cnt) {
          y->Val = y->InVal = x->Val;
          y->Size = 1;
          return y;
        } else {
          return NULL;
        }
      }
      if(D <= x->LS->Val) {
        y->LS = Delete(x->LS, ++CntN);
        if(!(y->LS)) {
          return x->RS;
        }
        y->RS = x->RS;
        y->InVal = y->LS->InVal;
        y->Val = x->Val;
      } else {
        y->RS = Delete(x->RS, ++CntN);
        if(!(y->RS)) {
          return x->LS;
        }
        y->LS = x->LS;
        y->Val = y->RS->Val;
        y->InVal = x->InVal;
      }
      y->Size = y->LS->Size + y->RS->Size;
      y->Cnt = y->LS->Cnt + y->RS->Cnt;
      Rotate(y);
      return y;
    }
    void Find(Node *x) {
      if(x->Size == 1) {
        if(x->Val < D) {
          Ans += x->Cnt;
        }
        return;
      }
      if(D > x->LS->Val) {
        Ans += x->LS->Cnt;
        Find(x->RS);
      } else {
        Find(x->LS);
      }
      return;
    }
    void Rank(Node *x) {
      if(x->Size == 1) {
        Ans = x->Val;
        return;
      }
      if(x->LS->Cnt < C) {
        C -= x->LS->Cnt;
        return Rank(x->RS);
      } else {
        return Rank(x->LS);
      }
    }
    int main() {
      n = RD();
      Ver[0] = N;
      N->Val = N->InVal = 0x3f3f3f3f;
      N->Cnt = N->Size = 1;
      for (register unsigned i(1); i <= n; ++i) {
        A = RD(), B = RD();
        switch (B){
          case (1):{
            D = RDsg();
            Insert(Ver[A], Ver[i] = ++CntN);
            break;
          }
          case (2):{
            D = RDsg();
            Ver[i] = Delete(Ver[A], ++CntN);
            break;
          }
          case (3):{
            D = RDsg();
            Ans = 1, Find(Ver[i] = Ver[A]);
            break;
          }
          case (4):{
            C = RD();
            Rank(Ver[i] = Ver[A]);
            break;
          }
          case (5):{
            D = RDsg();
            Ans = 0, Find(Ver[i] = Ver[A]);
            C = Ans, Rank(Ver[i]);
            break;
          }
          case (6):{
            D = RDsg();
            ++C, Ans = 1, Find(Ver[i] = Ver[A]);
            C = Ans, Rank(Ver[i]);
            break;
          }
        }
        if(B >= 3) {
          printf("%d
    ", Ans);
        }
      }
      return Wild_Donkey;
    }
    

    火车上的博客, 芜湖~

  • 相关阅读:
    白书数据结构基础总结
    UVA 10557 XYZZY 结题报告
    UVA 10047 The Monocycle 解题报告
    二叉查找树及其C语言实现
    堆排序及其c语言实现
    约瑟夫环问题小结
    KMP算法总结
    UVA 10129 Play on Words 解题报告
    深入浅出Node.js (8)
    洛谷 P1757 通天之分组背包
  • 原文地址:https://www.cnblogs.com/Wild-Donkey/p/15009298.html
Copyright © 2020-2023  润新知