BST - Binary Search Tree
容易发现对于插入
仔细观察,发现
于是我们依次插入每个数,查前驱后继,并且更新深度。
然后可以直接用 set
做,然而我写了个 Splay,结果跑得比 set
还慢。
#pragma GCC optimize("-Ofast")
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
#include <climits>
#include <string>
using namespace std;
const int N = 3e5 + 5;
long long dep[N];
class Splay
{
public:
int rt, idx;
struct Node
{
int son[2], fa, sz, cnt, val;
}tr[N];
void pushup(int u)
{
tr[u].sz = tr[tr[u].son[0]].sz + tr[tr[u].son[1]].sz + tr[u].cnt;
}
int get(int u)
{
return u == tr[tr[u].fa].son[1];
}
void rotate(int x)
{
int y = tr[x].fa, z = tr[y].fa;
int chkx = get(x), chky = get(y);
tr[y].son[chkx] = tr[x].son[chkx ^ 1];
if (tr[x].son[chkx ^ 1]) tr[tr[x].son[chkx ^ 1]].fa = y;
tr[x].son[chkx ^ 1] = y;
tr[y].fa = x;
tr[x].fa = z;
if (z) tr[z].son[chky] = x;
pushup(y);
pushup(x);
}
void splay(int x)
{
for (int f = tr[x].fa; f = tr[x].fa, f; rotate(x))
{
if (tr[f].fa) rotate(get(f) == get(x) ? f : x);
}
rt = x;
}
void ins(int x)
{
if (!rt)
{
rt = ++idx;
tr[rt].val = x;
tr[rt].cnt = 1;
pushup(rt);
return;
}
int u = rt, f, last;
while (true)
{
if (tr[u].val == x)
{
tr[u].cnt++;
pushup(u);
pushup(f);
splay(u);
return;
}
if (!u)
{
u = ++idx;
tr[u].fa = f;
tr[u].val = x;
tr[u].cnt = 1;
tr[f].son[last] = u;
pushup(u);
pushup(f);
splay(u);
return;
}
f = u;
last = x > tr[u].val;
u = tr[u].son[last];
}
}
int rank(int k)
{
int res = 0, u = rt;
while (true)
{
if (tr[u].val > k)
{
u = tr[u].son[0];
}
else if (tr[u].val == k)
{
res += tr[tr[u].son[0]].sz;
splay(u);
return res + 1;
}
else
{
res += tr[tr[u].son[0]].sz + tr[u].cnt;
u = tr[u].son[1];
}
}
}
int pre()
{
int u = tr[rt].son[0];
if (!u) return 0;
while (tr[u].son[1]) u = tr[u].son[1];
splay(u);
return tr[u].val;
}
int nxt()
{
int u = tr[rt].son[1];
if (!u) return 0;
while (tr[u].son[0]) u = tr[u].son[0];
splay(u);
return tr[u].val;
}
void CLEAR(int u)
{
tr[u].cnt = tr[u].fa = tr[u].son[0] = tr[u].son[1] = tr[u].sz = tr[u].val = 0;
}
void del(int x)
{
rank(x);
int u = rt;
if (tr[u].cnt > 1)
{
tr[u].cnt--;
pushup(u);
return;
}
if (!tr[u].son[0])
{
tr[tr[u].son[1]].fa = 0;
rt = tr[u].son[1];
CLEAR(u);
return;
}
if (!tr[u].son[1])
{
tr[tr[u].son[0]].fa = 0;
rt = tr[u].son[0];
CLEAR(u);
return;
}
pre();
tr[rt].son[1] = tr[u].son[1];
tr[tr[u].son[1]].fa = rt;
pushup(rt);
CLEAR(u);
}
}tr;
int n;
long long c;
int main()
{
tr.ins(INT_MIN);
tr.ins(INT_MAX);
scanf("%d", &n);
int rn = n;
while (n--)
{
int x;
scanf("%d", &x);
long long tp = 0LL;
tr.ins(x);
if (n == rn - 1)
{
printf("%lld\n", c);
continue;
}
int p = tr.pre();
tr.rank(x);
int nx = tr.nxt();
if (p != INT_MIN)
{
tp = dep[p];
}
if (nx != INT_MAX)
{
tp = max(tp, dep[nx]);
}
dep[x] = tp + 1LL;
c += tp + 1LL;
printf("%lld\n", c);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现