bzoj2002

本文详细解析了使用C++实现Splay树解决的2002年某编程题,包括输入读取、树节点操作、树的旋转、树的定位与调整等关键步骤。通过具体实例深入理解Splay树的特性与应用。

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);  
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值