• 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;
    }
    
    马上我就弃坑,宝贝。
  • 相关阅读:
    ASP.NET Core多环境配置文件问题
    .NET Core中Object Pool的简单使用
    Refit在ASP.NET Core中的实践
    HttpClientFactory与Steeltoe结合来完成服务发现
    用HttpClientFactory来实现简单的熔断降级
    看看.NET Core几个Options的简单使用
    再探Circuit Breaker之使用Polly
    谈谈Circuit Breaker在.NET Core中的简单应用
    在.NET Core中使用简单的插件化机制
    谈谈ASP.NET Core中的ResponseCaching
  • 原文地址:https://www.cnblogs.com/cicos/p/14963848.html
Copyright © 2020-2023  润新知