splay
前置
竞赛中比较常用。
闲扯:一般没有人会在考场上面写红黑树。
splay可以处理很多和线段树有关的问题,但是更加灵活。
splay是一棵比较平衡的二叉树,维护的是中序遍历的有序序列。
左旋和右旋保证树的高度是logn的,但是不改变树的中序遍历。
核心:每次操作一个节点,均将该节点旋转到树根。(证明过于复杂,我直接忽略),保证旋转的时间复杂度平均是logn的。
操作
1.splay(x, k)将点x旋转到k的下面。如果k是0,代表将x旋转到根。z -> y -> x,一条链,先转y再转x。有曲折的,先转x再转x
2.将一个序列插入到y的后面:首先找打y的后继z,首先将y转到跟,然后将z转到y的下面。因为z是y的后继,所以z在y的右子树上面,而且z的左子树为空,那么可以直接将序列插入到z的左子树上面去。
3.删除一段(l, r)转一下,然后删除r后继的左子树。
splay如何维护信息
1.每一个子树的节点个数。
2.flag懒标记,这个区间需不需要翻转。
3.push_up维护根节点的信息,push_down用来下传懒标记。
Splay
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m, rt = 0, cnt = 0;
struct tree
{
int siz, f, v, lz, son[2];
void init(int _v, int _p) {siz = 1, v = _v, f = _p; }
}t[N];
void push_down(int x)
{
if(t[x].lz)
{
t[t[x].son[0]].lz ^= 1, t[t[x].son[1]].lz ^= 1;
swap(t[x].son[0], t[x].son[1]);
t[x].lz = 0;
}
return ;
}
void push_up(int p)
{
t[p].siz = t[t[p].son[1]].siz + t[t[p].son[0]].siz + 1;
return ;
}
void rotate(int x)
{
int y = t[x].f, z = t[y].f;
t[x].f = z, t[z].son[y == t[z].son[1]] = x;
int ch = (x == t[y].son[1]);
t[y].son[ch] = t[x].son[ch ^ 1], t[t[x].son[ch ^ 1]].f = y;
t[y].f = x, t[x].son[ch ^ 1] = y;
push_up(y), push_up(x);
}
void splay(int x, int k)
{
while(t[x].f != k)
{
int y = t[x].f, z = t[y].f;
if(z != k)
{
if((t[y].son[1] == x) ^ (t[z].son[1] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(k == 0) rt = x;
return ;
}
int find_rank(int k)
{
int u = rt;
while(u)
{
push_down(u);
if(k <= t[t[u].son[0]].siz) u = t[u].son[0];
else if(k == t[t[u].son[0]].siz + 1) return u;
else k = k - t[t[u].son[0]].siz - 1, u = t[u].son[1];
}
return - 1;
}
void insert(int v)
{
int u = rt, p = 0;
while(u) p = u, u = t[u].son[v > t[u].v];
u = ++ cnt;
if(p != 0) t[p].son[v > t[p].v] = u;
t[u].init(v, p);
splay(u, 0);
}
void write(int x)
{
if(x == 0) return ;
push_down(x);
write(t[x].son[0]);
if(1 <= t[x].v && t[x].v <= n)printf("%d ", t[x].v);
write(t[x].son[1]);
return ;
}
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 = find_rank(l), r = find_rank(r + 2);
splay(l, 0), splay(r, l);
t[t[r].son[0]].lz ^= 1;
}
write(rt);
}
郁闷的出纳员
#include <bits/stdc++.h>
using namespace std;
const int N = 100005, inf = 0x3f3f3f3f;
int n, delta = 0, mn, tot = 0, rt = 0;
struct tree
{
int siz, par, son[2], val;
void init(int _val, int _par) {siz = 1, par = _par, val = _val; return; }
}t[N];
void push_up(int p) {t[p].siz = t[t[p].son[0]].siz + t[t[p].son[1]].siz + 1; }
void rotate(int x)
{
int y = t[x].par, z = t[y].par, k = (x == t[y].son[1]);
t[z].son[y == t[z].son[1]] = x, t[x].par = z;
t[y].son[k] = t[x].son[k ^ 1], t[t[x].son[k ^ 1]].par = y;
t[x].son[k ^ 1] = y, t[y].par = x;
push_up(y), push_up(x);
return ;
}
void splay(int x, int k)
{
while(t[x].par != k)
{
int y = t[x].par, z = t[y].par;
if(z != k)
{
if((y == t[z].son[1]) ^ (x == t[y].son[1])) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!k) rt = x;
return ;
}
void insert(int v)
{
int u = rt, p = 0;
while(u) p = u, u = t[u].son[v > t[u].val];
u = ++ tot; t[u].init(v, p);
if(p) t[p].son[v > t[p].val] = u;
splay(u, 0);
return ;
}
int get(int x)
{
int u = rt, ans = 0;
while(u)
{
if(t[u].val >= x) ans = u, u = t[u].son[0];
else u = t[u].son[1];
}
return ans;
}
int get_k(int k)
{
int u = rt;
// printf("%d!\n", u);
while(u)
{
if(t[t[u].son[0]].siz >= k) u = t[u].son[0];
else if(t[t[u].son[0]].siz + 1 == k) return t[u].val;
else k = k - t[t[u].son[0]].siz - 1, u = t[u].son[1];
}
return -1;
}
int main()
{
scanf("%d %d", &n, &mn);
insert(-inf), insert(inf);
for (int i = 1; i <= n; ++ i)
{
char opt[3];
int x;
scanf("%s %d", opt, &x);
if(opt[0] == 'I')
{
if(x >= mn) insert(x - delta);
}
else if(opt[0] == 'A') delta += x;
else if(opt[0] == 'S')
{
delta -= x;
int L = get(-inf), R = get(mn - delta);
splay(L, 0), splay(R, L), t[R].son[0] = 0;
push_up(R), push_up(L);
// splay(R, 0), splay(L, R); t[L].son[1] = 0;
// push_up(L), push_up(R);
}
else if(opt[0] == 'F')
{
if(x > t[rt].siz - 2)
{
printf("-1\n");
continue;
}
printf("%d\n", get_k(t[rt].siz - x) + delta);
}
}
printf("%d", tot - t[rt].siz);
return 0;
}
永无乡
#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
struct tree
{
int siz, val, par, son[2], idx;
void init (int _val, int _par, int _idx)
{
siz = 1, val = _val, par = _par, idx = _idx, son[0] = son[1] = 0; return ;
}
}t[N];
int fa[N], n, m, q, tot = 0, rt[N];
int findset(int x)
{
if(fa[x] == x) return x;
else return fa[x] = findset(fa[x]);
}
void push_up(int p) {t[p].siz = t[t[p].son[0]].siz + t[t[p].son[1]].siz + 1; }
void rotate(int x)
{
int y = t[x].par, z = t[y].par, k = x == t[y].son[1];
t[z].son[y == t[z].son[1]] = x, t[x].par = z;
t[y].son[k] = t[x].son[k ^ 1], t[t[x].son[k ^ 1]].par = y;
t[x].son[k ^ 1] = y, t[y].par = x;
push_up(y), push_up(x);
return ;
}
void splay(int x, int k, int b)
{
while(t[x].par != k)
{
int y = t[x].par, z = t[y].par;
if(z != k)
{
if((t[y].son[1] == x) ^ (t[z].son[1] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!k) rt[b] = x;
return ;
}
void insert(int v, int b, int idx)
{
int u = rt[b], p = 0;
while(u) p = u, u = t[u].son[v > t[u].val];
u = ++ tot;
t[u].init(v, p, idx);
if(p) t[p].son[v > t[p].val] = u;
splay(u, 0, b);
return ;
}
void dfs(int x, int b)
{
if(t[x].son[1]) dfs(t[x].son[1], b);
if(t[x].son[0]) dfs(t[x].son[0], b);
insert(t[x].val, b, t[x].idx);
return ;
}
int get(int b, int k)
{
int u = rt[b];
while(u)
{
if(t[t[u].son[0]].siz >= k) u = t[u].son[0];
else if(k == t[t[u].son[0]].siz + 1) return t[u].idx;
else k = k - t[t[u].son[0]].siz - 1, u = t[u].son[1];
}
return - 1;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i)
{
rt[i] = 0, fa[i] = i;
int v; scanf("%d", &v);
insert(v, i, i);
}
while(m --)
{
int u, v;
scanf("%d %d", &u, &v);
u = findset(u), v = findset(v);
if(u == v) continue;
if(t[rt[u]].siz > t[rt[v]].siz) dfs(v, u), fa[v] = u;
else dfs(u, v), fa[u] = v;
}
// for (int i = 1; i <= n; ++ i) printf("%d ", rt[findset(i)]);
// printf("\n");
scanf("%d", &q);
while(q --)
{
char opt[2]; int u, v; scanf("%s %d %d", opt, &u, &v);
if(opt[0] == 'B')
{
u = findset(u), v = findset(v);
if(u == v) continue;
if(t[rt[u]].siz > t[rt[v]].siz) dfs(v, u), fa[v] = u;
else dfs(u, v), fa[u] = v;
}
else
{
u = findset(u);
if(t[rt[u]].siz < v) printf("-1\n");
else printf("%d\n", get(u, v));
}
}
}
维护数列
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
const int inf = 0x3f3f3f3f;
int n, m, tot = 0, nodes[N], w[N], rt = 0;
struct tree
{
int val, par, son[2], siz;
int rev, al;
int sum, ms, ls, rs;
void init(int _val, int _par)
{
val = _val, par = _par, siz = 1, son[0] = son[1] = 0;
rev = al = 0;
sum = _val, ms = _val, ls = max(_val, 0), rs = max(_val, 0);
return ;
}
} t[N];
void push_up(int p)
{
tree &u = t[p], &l = t[t[p].son[0]], &r = t[t[p].son[1]];
u.siz = l.siz + r.siz + 1, u.sum = l.sum + r.sum + u.val;
u.ls = max(l.ls, l.sum + u.val + r.ls), u.rs = max(r.rs, r.sum + u.val + l.rs);
u.ms = max(r.ms, max(l.ms, l.rs + u.val + r.ls));//这里是两个端点的ms!
return ;
}
void rotate(int x)
{
int y = t[x].par, z = t[y].par;
int k = (x == t[y].son[1]);
t[x].par = z, t[z].son[t[z].son[1] == y] = x;
t[y].son[k] = t[x].son[k ^ 1], t[t[x].son[k ^ 1]].par = y;
t[x].son[k ^ 1] = y, t[y].par = x;
push_up(y), push_up(x);
return ;
}
void splay(int x, int k)
{
while(t[x].par != k)
{
int y = t[x].par, z = t[y].par;
if(z != k)
{
if((t[z].son[1] == y) ^ (t[y].son[1] == x)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!k) rt = x;
return ;
}
void push_down(int p)
{
tree &u = t[p], &l = t[t[p].son[0]], &r = t[t[p].son[1]];
if(u.al)
{
u.al = u.rev = 0;
if(u.son[0]) l.val = u.val, l.sum = l.val * l.siz, l.ls = max(0, l.sum), l.rs = max(0, l.sum), l.ms = max(l.val, l.sum), l.al = 1;
if(u.son[1]) r.val = u.val, r.sum = r.val * r.siz, r.ls = max(0, r.sum), r.rs = max(0, r.sum), r.ms = max(r.val, r.sum), r.al = 1;
}
else if(u.rev)
{
u.rev = 0;
l.rev ^= 1, swap(l.son[0], l.son[1]), swap(l.ls, l.rs);
r.rev ^= 1, swap(r.son[0], r.son[1]), swap(r.ls, r.rs);
}
return ;
}
int get_k(int k)
{
int u = rt;
while(u)
{
push_down(u);
if(t[t[u].son[0]].siz >= k) u = t[u].son[0];
else if(t[t[u].son[0]].siz + 1 == k) return u;
else k = k - t[t[u].son[0]].siz - 1, u = t[u].son[1];
}
return - 1;
}
int build(int l, int r, int b)
{
int mid = (l + r) >> 1, u = nodes[tot --];
t[u].init(w[mid], b);
if(l < mid) t[u].son[0] = build(l, mid - 1, u);
if(mid < r) t[u].son[1] = build(mid + 1, r, u);
push_up(u);
return u;
}
void dfs(int u)
{
if(t[u].son[0]) dfs(t[u].son[0]);
if(t[u].son[1]) dfs(t[u].son[1]);
nodes[++ tot] = u;
return ;
}
int main()
{
for (int i = 500000; i >= 1; -- i) nodes[++ tot] = i;
scanf("%d %d", &n, &m);
t[0].ms = w[0] = w[n + 1] = -inf;
for (int i = 1; i <= n; ++ i) scanf("%d", &w[i]);
rt = build(0, n + 1, 0);
while(m --)
{
char opt[20];
scanf("%s", opt);
if(!strcmp(opt, "INSERT"))
{
int pos, x;
scanf("%d %d", &pos, &x);
for (int i = 1; i <= x; ++ i) scanf("%d", &w[i]);
int l = get_k(pos + 1), r = get_k(pos + 2);
splay(l, 0), splay(r, l);
t[r].son[0] = build(1, x, r);
push_up(r), push_up(l);
}
else if(!strcmp(opt, "DELETE"))
{
int pos, x;
scanf("%d %d", &pos, &x);
int l = get_k(pos), r = get_k(pos + x + 1);
splay(l, 0), splay(r, l);
dfs(t[r].son[0]), t[r].son[0] = 0;
push_up(r), push_up(l);
}
else if(!strcmp(opt, "MAKE-SAME"))
{
int pos, x, c;
scanf("%d %d %d", &pos, &x, &c);
int l = get_k(pos), r = get_k(pos + x + 1);
splay(l, 0), splay(r, l);
tree &u = t[t[r].son[0]];
u.val = c, u.sum = c * u.siz, u.ls = u.rs = max(0, u.sum);
u.ms = max(c, u.sum), u.al = 1;
push_up(r), push_up(l);
}
else if(!strcmp(opt, "REVERSE"))
{
int pos, x;
scanf("%d %d", &pos, &x);
int l = get_k(pos), r = get_k(pos + x + 1);
splay(l, 0), splay(r, l);
tree &u = t[t[r].son[0]];
u.rev ^= 1;
swap(u.ls, u.rs), swap(u.son[0], u.son[1]);
push_up(r), push_up(l);
}
else if(!strcmp(opt, "GET-SUM"))
{
int pos, x;
scanf("%d %d", &pos, &x);
int l = get_k(pos), r = get_k(pos + x + 1);
splay(l, 0), splay(r, l);
push_up(r), push_up(l);
printf("%d\n", t[t[r].son[0]].sum);
}
else if(!strcmp(opt, "MAX-SUM"))
{
printf("%d\n", t[rt].ms);
}
}
return 0;
}

浙公网安备 33010602011771号