lct 练手题
(谁说用的那个叫splay 明明spaly
/**************************************************************
Problem: 2002
User: leijp
Language: C++
Result: Accepted
Time:1432 ms
Memory:4908 kb
****************************************************************/
#include <cstdio>
int n,m,k[200010];
int pre[200010],sz[200010],ch[200010][2];
bool rt[200010];
int read_int () {
char c = getchar();
int re = 0;
for(;c > '9' || c < '0'; c = getchar());
for(;c >= '0' && c <= '9';c = getchar())
re = re * 10 + c - '0';
return re;
}
void pu (int u) {
sz[u] = sz[ch[u][0]] + sz[ch[u][1]] + 1;
}
void rot (int u,int d) {
//pre ch sz rt
ch[pre[u]][d ^ 1] = ch[u][d];
if(ch[u][d])
pre[ch[u][d]] = pre[u];
ch[u][d] = pre[u];
int t = pre[pre[u]];
pre[pre[u]] = u;
pre[u] = t;
if(!rt[ch[u][d]]) {
if(t) {
if(ch[t][0] == ch[u][d])
ch[t][0] = u;
else ch[t][1] = u;
}
}
pu(ch[u][d]);
pu(u);
if(rt[ch[u][d]]) {
rt[ch[u][d]] = 0;
rt[u] = 1;
}
}
void splay (int u) {
while(!rt[u]) {
if(rt[pre[u]]) {
if(ch[pre[u]][0] == u)
rot(u,1);
else rot(u,0);
}
else {
int d = ch[pre[pre[u]]][0] == pre[u];
if(ch[pre[u]][d] == u) {
rot(u,d ^ 1);
rot(u,d);
}
else {
rot(u,d);
rot(u,d);
}
}
}
}
void acc (int u) {
int v = 0;
for(;u;u = pre[v = u]) {
splay(u);
if(ch[u][1]) {
rt[ch[u][1]] = 1;
pre[ch[u][1]] = u;
}
rt[ch[u][1] = v] = 0;
pu(u);
}
}
int main () {
n = read_int();
for(int i = 1;i <= n;++i) {
k[i] = read_int();
if(i + k[i] <= n)
pre[i] = i + k[i];
rt[i] = 1;
sz[i] = 1;
}
m = read_int();
for(int i = 1;i <= m;++i) {
int op = read_int();
int p = read_int() + 1;
acc(p);
splay(p);
if(op == 1)
printf("%d\n",sz[ch[p][0]] + 1);
else {
k[p] = read_int();
if(ch[p][0]) {
rt[ch[p][0]] = 1;
pre[ch[p][0]] = pre[p];
ch[p][0] = 0;
}
if(p + k[p] > n)
pre[p] = 0;
else pre[p] = p + k[p];
pu(p);
}
}
}
本文详细解析了使用C++实现Splay树解决的2002年某编程题,包括输入读取、树节点操作、树的旋转、树的定位与调整等关键步骤。通过具体实例深入理解Splay树的特性与应用。

1014

被折叠的 条评论
为什么被折叠?



