平衡树(模板 and 题目)记录

本文深入探讨了两种高效的数据结构——替罪羊树和斐波那契堆树(Fibonacci Heap Tree),它们在解决动态集合问题时展现出了优秀的性能。替罪羊树通过保持节点平衡来确保操作的低复杂度,而斐波那契堆树则在维护值、区间操作等方面表现出色。此外,文章还介绍了如何利用这些数据结构进行插入、删除、查找和排名等操作,以及如何在实际问题中应用它们来优化算法的效率。
摘要由CSDN通过智能技术生成

平衡树

替罪羊树

#include <bits/stdc++.h>

using namespace std;

const double alpha = 0.725;
const int N = 2e6 + 10;

struct Spgtree {
  int ls[N], rs[N], val[N], num[N], fac[N], sz[N], sum[N], cnt, root;

  int top, stk[N];

  void update(int rt) {
    fac[rt] = fac[ls[rt]] + fac[rs[rt]] + (num[rt] ? 1 : 0);
    sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;
    sum[rt] = sum[ls[rt]] + sum[rs[rt]] + num[rt];
  }

  void dfs(int rt) {
    if (!rt) {
      return ;
    }
    dfs(ls[rt]);
    if (num[rt]) {
      stk[++top] = rt;
    }
    dfs(rs[rt]);
  }

  int build(int l, int r) {
    if (l > r) {
      return 0;
    }
    if (l == r) {
      ls[stk[l]] = rs[stk[l]] = 0;
      update(stk[l]);
      return stk[l];
    }
    int mid = l + r >> 1;
    ls[stk[mid]] = build(l, mid - 1), rs[stk[mid]] = build(mid + 1, r);
    update(stk[mid]);
    return stk[mid];
  }

  void rebuild(int &rt) {
    top = 0;
    dfs(rt);
    rt = build(1, top);
  }

  bool imbalence(int rt) {
    return sum[rt] && (alpha * sz[rt] <= max(sz[ls[rt]], sz[rs[rt]]) || alpha * sz[rt] >= fac[rt]);
  }

  void insert(int &rt, int value) {
    if (!rt) {
      rt = ++cnt, val[rt] = value, num[rt] = 1;
      update(rt);
      return ;
    }
    if (val[rt] == value) {
      num[rt]++;
    }
    else if (value < val[rt]) {
      insert(ls[rt], value);
    }
    else {
      insert(rs[rt], value);
    }
    update(rt);
    if (imbalence(rt)) {
      rebuild(rt);
    }
  }

  void insert(int value) {
    insert(root, value);
  }

  void erase(int &rt, int value) {
    if (!rt) {
      return ;
    }
    if (val[rt] == value) {
      num[rt]--;
    }
    else if (value < val[rt]) {
      erase(ls[rt], value);
    }
    else {
      erase(rs[rt], value);
    }
    update(rt);
    if (imbalence(rt)) {
      rebuild(rt);
    }
  }

  void erase(int value) {
    erase(root, value);
  }

  int get_rank(int value) {
    int rt = root, rank = 1;
    while (rt) {
      if (value <= val[rt]) {
        rt = ls[rt];
      }
      else {
        rank += num[rt] + sum[ls[rt]];
        rt = rs[rt];
      }
    }
    return rank;
  }

  int get_num(int rank) {
    int rt = root;
    while (rt) {
      if (num[rt] && sum[ls[rt]] < rank && sum[ls[rt]] + num[rt] >= rank) {
        break;
      }
      if (sum[ls[rt]] >= rank) {
        rt = ls[rt];
      }
      else {
        rank -= sum[ls[rt]] + num[rt];
        rt = rs[rt];
      }
    }
    return val[rt];
  }
}tree;

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  return 0;
}

fhq treap

维护值

#include <bits/stdc++.h>

using namespace std;

const int N = 2e6 + 10;

mt19937 rnd(233);

struct fhqtreap {
  int ls[N], rs[N], val[N], key[N], sz[N], root, cnt;

  inline int new_node(int value) {
    cnt++;
    val[cnt] = value, sz[cnt] = 1, key[cnt] = rnd();
    return cnt;
  }

  void update(int rt) {
    sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;
  }

  void split(int rt, int value, int &x, int &y) {
    if (!rt) {
      x = y = 0;
      return ;
    }
    if (val[rt] <= value) {
      x = rt;
      split(rs[rt], value, rs[rt], y);
    }
    else {
      y = rt;
      split(ls[rt], value, x, ls[rt]);
    }
    update(rt);
  }

  int merge(int x, int y) {
    if (!x || !y) {
      return x | y;
    }
    if (key[x] < key[y]) {
      ls[y] = merge(x, ls[y]);
      update(y);
      return y;
    }
    else {
      rs[x] = merge(rs[x], y);
      update(x);
      return x;
    }
  }

  void insert(int value) {
    int x, y;
    split(root, value, x, y);
    root = merge(merge(x, new_node(value)), y);
  }

  void erase(int value) {
    int x, y, z;
    split(root, value, x, z);
    split(x, value - 1, x, y);
    y = merge(ls[y], rs[y]);
    root = merge(merge(x, y), z);
  }

  int get_num(int rank) {
    int rt = root;
    while (rt) {
      if (sz[ls[rt]] + 1 == rank) {
        break;
      }
      else if (sz[ls[rt]] >= rank) {
        rt = ls[rt];
      }
      else {
        rank -= sz[ls[rt]] + 1;
        rt = rs[rt];
      }
    }
    return val[rt];
  }

  int get_rank(int value) {
    int x, y, rank;
    split(root, value - 1, x, y);
    rank = sz[x] + 1;
    root = merge(x, y);
    return rank;
  }

  int pre(int value) {
    int x, y, rt;
    split(root, value - 1, x, y);
    rt = x;
    while (rs[rt]) {
      rt = rs[rt];
    }
    root = merge(x, y);
    return val[rt];
  }

  int suc(int value) {
    int x, y, rt;
    split(root, value, x, y);
    rt = y;
    while (ls[rt]) {
      rt = ls[rt];
    }
    root = merge(x, y);
    return val[rt];
  }
}tree;

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  return 0;
}

维护区间

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

mt19937 rnd(233);

struct fhqtreap {
  int ls[N], rs[N], val[N], key[N], sz[N], rev[N], cnt, root;

  int new_node(int value) {
    cnt++;
    val[cnt] = value, key[cnt] = rnd(), sz[cnt] = 1;
    return cnt;
  }

  void push_down(int rt) {
    if (rev[rt]) {
      swap(ls[rt], rs[rt]);
      rev[ls[rt]] ^= 1, rev[rs[rt]] ^= 1;
      rev[rt] = 0;
    }
  }

  void push_up(int rt) {
    sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;
  }

  void split(int rt, int siz, int &x, int &y) {
    if (!rt) {
      x = y = 0;
      return ;
    }
    push_down(rt);
    if (sz[ls[rt]] < siz) {
      x = rt;
      split(rs[rt], siz - sz[ls[rt]] - 1, rs[rt], y);
    }
    else {
      y = rt;
      split(ls[rt], siz, x, ls[rt]);
    }
    push_up(rt);
  }

  int merge(int x, int y) {
    if (!x || !y) {
      return x | y;
    }
    if (key[x] < key[y]) {
      push_down(x);
      rs[x] = merge(rs[x], y);
      push_up(x);
      return x;
    }
    else {
      push_down(y);
      ls[y] = merge(x, ls[y]);
      push_up(y);
      return y;
    }
  }

  void reverse(int l, int r) {
    int x, y, z;
    split(root, l - 1, x, y);
    split(y, r - l + 1, y, z);
    rev[y] ^= 1;
    root = merge(merge(x, y), z);
  }

  void print(int rt) {
    if (!rt) {
      return ;
    }
    push_down(rt);
    print(ls[rt]);
    printf("%d ", val[rt]);
    print(rs[rt]);
  }

  void print() {
    print(root);
  }

  void build(int n) {
    for (int i = 1; i <= n; i++) {
      root = merge(root, new_node(i));
    }
  }
}tree;

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, m;
  scanf("%d %d", &n, &m);
  tree.build(n);
  for (int i = 1; i <= m; i++) {
    int l, r;
    scanf("%d %d", &l, &r);
    tree.reverse(l, r);
  }
  tree.print(), putchar('\n');
  return 0;
}

P3850 [TJOI2007]书架

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

string str[N];

mt19937 rnd(233);

struct Treap {
  int ls[N], rs[N], val[N], sz[N], key[N], root, cnt;

  void push_up(int rt) {
    sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;
  }

  int new_node(int value) {
    cnt++;
    val[cnt] = value, sz[cnt] = 1, key[cnt] = rnd();
    return cnt;
  }

  void split(int rt, int maxn, int &x, int &y) {
    if (!rt) {
      x = y = 0;
      return ;
    }
    if (sz[ls[rt]] < maxn) {
      x = rt;
      split(rs[rt], maxn - sz[ls[rt]] - 1, rs[x], y);
    }
    else {
      y = rt;
      split(ls[rt], maxn, x, ls[rt]);
    }
    push_up(rt);
  }

  int merge(int x, int y) {
    if (!x || !y) {
      return x | y;
    }
    if (key[x] < key[y]) {
      rs[x] = merge(rs[x], y);
      push_up(x);
      return x;
    }
    else {
      ls[y] = merge(x, ls[y]);
      push_up(y);
      return y;
    }
  }

  void insert(int pos, int value) {
    int x, y;
    split(root, pos, x, y);
    root = merge(merge(x, new_node(value)), y);
  }

  int get_num(int rank) {
    int x, y, z, ans;
    split(root, rank, x, y);
    split(y, 1, y, z);
    ans = val[y];
    root = merge(merge(x, y), z);
    return ans;
  }

  void build(int n) {
    for (int i = 1; i <= n; i++) {
      root = merge(root, new_node(i));
    }
  }
}tree;

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, m, q, cnt = 0;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> str[++cnt];
  }
  tree.build(cnt);
  cin >> m;
  for (int i = 1, pos; i <= m; i++) {
    cin >> str[++cnt] >> pos;
    tree.insert(pos, cnt);
  }
  cin >> q;
  for (int i = 1, x; i <= q; i++) {
    cin >> x;
    cout << str[tree.get_num(x)] << "\n";
  }
  return 0;
}

P2596 [ZJOI2006]书架

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

mt19937 rnd(233);

int minn, maxn;

struct Tree {
  int ls[N], rs[N], val[N], sz[N], key[N], root, cnt;

  
  void push_up(int rt) {
    sz[rt] = sz[ls[rt]] + sz[rs[rt]] + 1;
  }

  int new_node(int value, int pos) {
    val[value] = pos, sz[value] = 1, key[value] = rnd();
    return value;
  }

  void split(int rt, int value, int &x, int &y) {
    if (!rt) {
      x = y = 0;
      return ;
    }
    if (val[rt] <= value) {
      x = rt;
      split(rs[rt], value, rs[rt], y);
    }
    else {
      y = rt;
      split(ls[rt], value, x, ls[rt]);
    }
    push_up(rt);
  }

  int merge(int x, int y) {
    if (!x || !y) {
      return x | y;
    }
    if (key[x] < key[y]) {
      rs[x] = merge(rs[x], y);
      push_up(x);
      return x;
    }
    else {
      ls[y] = merge(x, ls[y]);
      push_up(y);
      return y;
    }
  }

  int get_num(int rt, int rank) {
    while (rt) {
      if (sz[ls[rt]] + 1 == rank) {
        break;
      }
      if (sz[ls[rt]] >= rank) {
        rt = ls[rt];
      }
      else {
        rank -= sz[ls[rt]] + 1;
        rt = rs[rt];
      }
    }
    return rt;
  }

  int get_num(int rank) {
    return get_num(root, rank);
  }

  void insert(int value, int pos) {
    int x, y;
    split(root, pos, x, y);
    root = merge(merge(x, new_node(value, pos)), y);
  }

  void update(int value, int op) {
    int x, y, z;
    split(root, val[value], x, z);
    split(x, val[value] - 1, x, y);
    if (op) {
      val[value] = --minn;
      root = merge(merge(y, x), z);
    }
    else {
      val[value] = ++maxn;
      root = merge(merge(x, z), y);
    }
  }

  void reverse(int value, int op) {
    if (!op) {
      return ;
    }
    if (op == 1) {
      int x, y, z, w;
      split(root, val[value], x, z);
      split(x, val[value] - 1, x, y);
      int t = get_num(z, 1);
      split(z, val[t], z, w);
      swap(val[y], val[z]);
      root = merge(merge(x, z), merge(y, w));
    }
    else {
      int x, y, z, w;
      split(root, val[value] - 1, x, z);
      split(z, val[value], z, w);
      int t = get_num(x, sz[x]);
      split(x, val[t] - 1, x, y);
      swap(val[y], val[z]);
      root = merge(merge(x, z), merge(y, w));
    }
  }

  int get_rank(int value) {
    int x, y, ans;
    split(root, val[value] - 1, x, y);
    ans = sz[x];
    root = merge(x, y);
    return ans;
  }
}tree;

int main() {
  // freopen("in.txt", "r", stdin);
  // freopen("out.txt", "w", stdout);
  // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, m;
  scanf("%d %d", &n, &m);
  minn = 1, maxn = n;
  for (int i = 1, x; i <= n; i++) {
    scanf("%d", &x);
    tree.insert(x, i);
  }
  char op[10];
  for (int i = 1, s, t; i <= m; i++) {
    scanf("%s %d", op, &s);
    if (op[0] == 'T') {
      tree.update(s, 1);
    }
    else if (op[0] == 'B') {
      tree.update(s, 0);
    }
    else if (op[0] == 'I') {
      scanf("%d", &t);
      tree.reverse(s, t);
    }
    else if (op[0] == 'A') {
      printf("%d\n", tree.get_rank(s));
    }
    else {
      printf("%d\n", tree.get_num(s));
    }
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值