维护一棵spaly(单旋splay),要求你支持以下五种操作:
其中每个操作的代价为所影响节点的深度。
完整题面自己看吧,这里只有一个简要的……
考虑单旋(删除)最小(大)值,经过手玩可以发现,其实只是把最小(大)值与它的父亲断开,然后与当前根节点相连,且根节点是它的右(左)儿子。
至于插入操作,不难发现插入节点不是其前驱的右儿子,就是其后继的左儿子。所以记录每个节点的左右儿子,然后用 set s e t 查找即可。
整棵树的操作用 LCT L C T 维护即可。
#include
using namespace std;
const int maxn = 100005;
int m;
inline int gi()
{
char c = getchar();
while (c < '0' || c > '9') c = getchar();
int sum = 0;
while ('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
return sum;
}
int root, f[maxn], ch[maxn][2], siz[maxn], rev[maxn];
#define isroot(x) (ch[f[x]][0] != x && ch[f[x]][1] != x)
#define get(x) (ch[f[x]][1] == x)
#define update(x) siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1
inline void rotate(int x)
{
int fa = f[x], gfa = f[fa], k = get(x);
if (!isroot(fa)) ch[gfa][get(fa)] = x;
ch[fa][k] = ch[x][k ^ 1]; f[ch[x][k ^ 1]] = fa;
ch[x][k ^ 1] = fa; f[fa] = x;
f[x] = gfa;
update(fa); update(x);
}
inline void pushdown(int x)
{
if (!x || !rev[x]) return ;
if (ch[x][0]) rev[ch[x][0]] ^= 1;
if (ch[x][1]) rev[ch[x][1]] ^= 1;
rev[x] ^= 1;
swap(ch[x][0], ch[x][1]);
}
int stk[maxn], top;
inline void splay(int x)
{
stk[top = 1] = x;
while (!isroot(x)) stk[++top] = x = f[x];
while (top) pushdown(stk[top--]);
x = stk[1];
while (!isroot(x)) {
int fa = f[x];
if (!isroot(fa)) get(x) ^ get(fa) ? rotate(x) : rotate(fa);
rotate(x);
}
}
inline void access(int x)
{
for (int y = 0; x; y = x, x = f[x])
splay(x), ch[x][1] = y, update(x);
}
inline void make_root(int x) {access(x); splay(x); rev[x] ^= 1;}
inline void link(int x, int y) {make_root(x); f[x] = y; update(y);}
inline void cut(int x, int y) {make_root(x); access(y); splay(y); f[x] = ch[y][0] = 0;}
set<int> S;
map<int, int> M;
int fa[maxn], ls[maxn], rs[maxn], tot;
void insert(int x)
{
M[x] = ++tot;
if (S.empty()) {
S.insert(x); root = tot;
puts("1"); return;
}
set<int>::iterator p = S.upper_bound(x);
int k;
if ((p == S.end()) || ls[k = M[*p]]) {
int k = M[*(--p)];
link(tot, k); rs[k] = tot; fa[tot] = k;
} else {
int k = M[*p];
link(tot, k); ls[k] = tot; fa[tot] = k;
}
S.insert(x);
make_root(root); access(tot); splay(tot);
printf("%d\n", siz[tot]);
}
inline void splay_min()
{
int x = M[*S.begin()];
if (root == x) {puts("1"); return;}
make_root(root); access(x); splay(x);
printf("%d\n", siz[x]);
cut(x, fa[x]);
link(x, root);
if (rs[x]) cut(x, rs[x]), link(fa[x], rs[x]), fa[rs[x]] = fa[x];
ls[fa[x]] = rs[x];
fa[x] = 0; fa[root] = x; rs[x] = root;
root = x;
}
inline void splay_max()
{
int x = M[*--S.end()];
if (root == x) {puts("1"); return;}
make_root(root); access(x); splay(x);
printf("%d\n", siz[x]);
cut(x, fa[x]); link(x, root);
if (ls[x]) cut(x, ls[x]), link(fa[x], ls[x]), fa[ls[x]] = fa[x];
rs[fa[x]] = ls[x];
fa[x] = 0; fa[root] = x; ls[x] = root;
root = x;
}
inline void del_min()
{
int x = M[*S.begin()]; S.erase(S.begin());
if (root == x) {puts("1"); if (rs[x]) cut(x, rs[x]); fa[rs[x]] = 0; root = rs[x]; return;}
make_root(root); access(x); splay(x);
printf("%d\n", siz[x]);
cut(x, fa[x]);
if (rs[x]) cut(x, rs[x]), link(fa[x], rs[x]), fa[rs[x]] = fa[x];
ls[fa[x]] = rs[x];
}
void del_max()
{
int x = M[*--S.end()]; S.erase(--S.end());
if (root == x) {puts("1"); if (ls[x]) cut(x, ls[x]); fa[ls[x]] = 0; root = ls[x]; return;}
make_root(root); access(x); splay(x);
printf("%d\n", siz[x]);
cut(x, fa[x]);
if (ls[x]) cut(x, ls[x]), link(fa[x], ls[x]), fa[ls[x]] = fa[x];
rs[fa[x]] = ls[x];
}
int main()
{
m = gi();
while (m--) {
int c = gi();
if (c == 1) insert(gi());
else if (c == 2) splay_min();
else if (c == 3) splay_max();
else if (c == 4) del_min();
else if (c == 5) del_max();
}
return 0;
}