zoukankan      html  css  js  c++  java
  • splay回忆提纲

    在二叉树上操作。splay(x, pa)这个函数把x旋转成pa的儿子,且这棵树和原来等价(旋转是可以等价旋转的)。

    splay()内用到rotate(x)函数,rotate(x)就是等价地把x往上转一层。splay中对rotate有关照:假称x的父亲是y,y的父亲是z,则对于x,y,z连接方向不同的情况进行不同处理,写起来还是很简单明了的。

    文艺平衡树 区间反转

    前后插入0和n+1,旋转l,r时,把rank(注意是加入0后的rank不是原排名)l提到root,把rank r+2提到root的右儿子,然后给root的右儿子的左儿子上反转标记。

    文艺平衡树代码

    注意!insert中必须有splay(x, 0),以更新初始root信息、维持平衡。

    会出现y和z都是0的情况,但是记牢这么写没问题就行。

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, m, rt;
    struct Node {
      int val;
      int fa;
      int ch[2];
      int siz;
      int tag;
      void init(int xval, int xfa) {
        val = xval;
        fa = xfa;
        ch[0] = ch[1] = 0;
        siz = 1;
        tag = 0;
      }
    } node[100010]; int cnt = 0;
    
    void pushdown(int x) {
      if (node[x].tag) {
        node[node[x].ch[0]].tag ^= 1;
        node[node[x].ch[1]].tag ^= 1;
        swap(node[x].ch[0], node[x].ch[1]);
        node[x].tag = 0;
      }
    }
    
    void update(int x) {
      node[x].siz = node[node[x].ch[0]].siz + node[node[x].ch[1]].siz + 1;
    }
    
    void rotate(int x) {
      int y = node[x].fa, z = node[y].fa;
      int xid = node[y].ch[1] == x, yid = node[z].ch[1] == y;
      node[z].ch[yid] = x;
      node[x].fa = z;
      node[y].ch[xid] = node[x].ch[xid ^ 1];
      node[node[x].ch[xid ^ 1]].fa = y;
      node[x].ch[xid ^ 1] = y;
      node[y].fa = x;
      update(x), update(y);
    }
    
    void splay(int x, int pa) { // let x be a son of pa
      while (node[x].fa != pa) {
        int y = node[x].fa, z = node[y].fa;
        if (z != pa) 
          (y == node[z].ch[1]) == (x == node[y].ch[1]) ? rotate(y) : rotate(x);
        rotate(x);
      }
      if (pa == 0)
        rt = x;
    }
    
    void insert(int val) {
      int p = rt, fa = 0;
      while (p)
        fa = p, p = node[p].ch[val > node[p].val];
      int x = ++cnt;
      if (fa != 0)
        node[fa].ch[val > node[fa].val] = x;
      node[x].init(val, fa);
      splay(x, 0); // i dont know why
    }
    
    int findk(int k) {
      int x = rt;
      while (1) {
        pushdown(x);
        if (k == node[node[x].ch[0]].siz + 1) break;
        if (k <= node[node[x].ch[0]].siz) x = node[x].ch[0];
        else k -= node[node[x].ch[0]].siz + 1, x = node[x].ch[1];
      }
      return x;
    }
    
    void print(int x) {
      if (x == 0) return;
      pushdown(x);
      print(node[x].ch[0]);
      if (1 <= node[x].val and node[x].val <= n)
        printf("%d ", node[x].val);
      print(node[x].ch[1]);
    }
    
    int main() {
      scanf("%d %d", &n, &m);
      for (int i = 0; i <= n + 1; ++i)
        insert(i);
      while (m--) {
        int l, r; scanf("%d %d", &l, &r);
        l = findk(l);
        // it's actually node l - 1
        r = findk(r + 2); 
        // cuz there is 0 in the tree
        splay(l, 0);
        splay(r, l);
        node[node[node[rt].ch[1]].ch[0]].tag ^= 1;
        // yep
      }
      print(rt);
      return 0;
    }
    
    马上我就弃坑,宝贝。
  • 相关阅读:
    配置域名服务器报错named[822]: dns_rdata_fromtext /etc/bind/db.asertest.com mail not a valid number
    Cookie/Session机制详解
    java中一个数组不能放不同数据类型的值
    javascript中 (function(){})();如何理解?
    图表实现基于SVG或Canvas
    千层饼图 年轮图
    element select下拉框绑定number类型
    Vue和JQuery相比,除了节省了开发成本,还有什么优点?
    前端领域的BEM到底是什么
    js数组操作find查找特定值结合es6特性
  • 原文地址:https://www.cnblogs.com/cicos/p/14963848.html
Copyright © 2011-2022 走看看