voidsplay(int x, int k) { while (tr[x].p != k) { int y = tr[x].p, z = tr[y].p; if (z != k) if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x); elserotate(y); rotate(x); } if (!k) root = x; // 如果k的值为0,表示将x转至根节点,需要将root改为x }
voidinsert_points(int v) { int u = root, p = 0; while(u) p = u, u = tr[u].s[v > tr[u].v]; // 不易爆栈的递归查找 u = ++ idx; if (p) tr[p].s[v > tr[p].v] = u; // 如果该点不为根,才需要将它的父节点指向它 tr[u].init(v, p); // 初始化 splay(u, 0); }
4.序列插入——insert_interval( start , number ) :
向 Splay树 中插入一个长度为的序列
这种插入方式同样可以用于进行单点插入操作
实现原理 :
待补充
通用代码 :
1 2 3 4 5 6 7 8 9
voidinsert_interval(int start, int number) { for (int i = 0; i < number; i ++ ) scanf("%d", &w[i]); int l = getk(start + 1), r = getk(start + 2); splay(l, 0), splay(r, l); int u = build(0, number - 1, r); tr[r].s[0] = u; pushup(r), pushup(l); }
voidrotate(int x) { int y = tr[x].p, z = tr[y].p; int k = tr[y].s[1] == x; tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y; tr[x].s[k ^ 1] = y, tr[y].p = x; pushup(y), pushup(x); }
voidsplay(int x, int k) { while (tr[x].p != k) { int y = tr[x].p, z = tr[y].p; if (z != k) if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x); elserotate(y); rotate(x); } if (!k) root = x; }
voidinsert(int v) { int u = root, p = 0; while (u) p = u, u = tr[u].s[v > tr[u].v]; u = ++ idx; if (p) tr[p].s[v > tr[p].v] = u; tr[u].init(v, p); splay(u, 0); }
intget_k(int k) { int u = root; while (true) { pushdown(u); if (tr[tr[u].s[0]].size >= k) u = tr[u].s[0]; elseif (tr[tr[u].s[0]].size + 1 == k) return u; else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1]; } return-1; }
voidoutput(int u) { pushdown(u); if (tr[u].s[0]) output(tr[u].s[0]); if (tr[u].v >= 1 && tr[u].v <= n) printf("%d ", tr[u].v); if (tr[u].s[1]) output(tr[u].s[1]); }
intmain() { 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 = get_k(l), r = get_k(r + 2); splay(l, 0), splay(r, l); tr[tr[r].s[0]].flag ^= 1; } output(root); return0; }