[原创题] max 左偏树
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[原创题] max 左偏树相关的知识,希望对你有一定的参考价值。
Simple
你要维护一个多重集合 $S$ .
? 最初集合为空.
? 一共有 $m$ 次操作, 每次操作形如下面两种中的一种:
? $1~a$ : 在多重集合 $S$ 中插入一个 $a$ .
? $2$ : 查询 $\max_{i \in S}i$ .
? $m \le {10} ^ 5, a \le {10} ^ 9$ , 强制在线.
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <algorithm> using namespace std; #define F(i, a, b) for (register int i = (a); i <= (b); i++) const int N = 100005; int m; int rt, tot, c[N][2], d[N], key[N]; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; } inline int Newnode(int w) { return d[++tot] = 1, key[tot] = w, tot; } inline void Merge(int &x, int y) { if (!x) { x = y; return; } if (!y) return; if (key[x] < key[y]) { int t = x; x = y, y = t; } Merge(c[x][1], y); if (d[c[x][0]] < d[c[x][1]]) swap(c[x][0], c[x][1]); d[x] = d[c[x][1]] + 1; } int main(void) { m = rd(); F(i, 1, m) { int k = rd(); if (k == 1) { int w = rd(); int t = Newnode(w); Merge(rt, t); } else printf("%d\n", key[rt]); } return 0; }
Normal
? 你要维护一个多重集合 $S$ .
? 最初集合为空.
? 一共有 $m$ 次操作, 每次操作形如下面两种中的一种:
? $1~a$ : 在多重集合 $S$ 中插入一个 $a$ .
? $2$ : 查询 $\max_{i \in S}i$ .
? $3~a$ : 在多重集合 $S$ 中删除一个 $a$ .
? $m \le {10} ^ 5, a \le {10} ^ 9$ , 强制在线.
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <vector> #include <map> using namespace std; #define F(i, a, b) for (register int i = (a); i <= (b); i++) const int N = 100005; int m; map<int, int> id; int ind; vector<int> g[N]; int rt, tot, c[N][2], par[N], d[N], key[N]; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; } inline int Newnode(int w) { return d[++tot] = 1, key[tot] = w, tot; } inline void Merge(int &x, int y) { if (!x) { x = y; return; } if (!y) return; if (key[x] < key[y]) { int t = x; x = y, y = t; } Merge(c[x][1], y), par[c[x][1]] = x; if (d[c[x][0]] < d[c[x][1]]) swap(c[x][0], c[x][1]); d[x] = d[c[x][1]] + 1; } inline void Insert(int w) { int t = Newnode(w); Merge(rt, t); int ID = !id[w] ? id[w] = ++ind : id[w]; g[ID].push_back(t); } inline void Delete(int w) { int ID = id[w], t = g[ID].back(); g[ID].pop_back(); if (t == rt) { int L = c[rt][0], R = c[rt][1]; par[L] = c[rt][0] = par[R] = c[rt][1] = 0; Merge(L, R), rt = L; } else { int L = c[t][0], R = c[t][1], A = par[t]; par[L] = c[t][0] = par[R] = c[t][1] = par[t] = c[A][c[A][1] == t] = 0; for (; par[A] > 0; A = par[A]) { if (d[c[A][0]] < d[c[A][1]]) swap(c[A][0], c[A][1]); d[A] = d[c[A][1]] + 1; } Merge(L, R); Merge(rt, L); } } int main(void) { m = rd(); F(i, 1, m) { int k = rd(); if (k == 1) { int w = rd(); Insert(w); } else if (k == 2) printf("%d\n", key[rt]); else { int w = rd(); Delete(w); } } return 0; }
Normal 2
支持可持久化.
inline int Merge(int x, int y) { if (!x || !y) return x + y; if (key[x] < key[y]) swap(x, y); int t = Copynode(x); c[t][1] = Merge(c[x][1], y); if (d[c[t][0]] < d[c[t][1]]) swap(c[t][0], c[t][1]); d[t] = d[c[t][1]] + 1; return t; }
以上是关于[原创题] max 左偏树的主要内容,如果未能解决你的问题,请参考以下文章