赇助Splay写法

P6136 【模板】普通平衡树(数据加强版)

Neutralized @ 2022-02-08 20:28:04

主要是 \texttt{get rank} 函数
之前原版里有一个可以过的函数:

inline int getrnk(int x){
    ri cur=root,ret=0;
    while(cur){
        if(val[cur]==x){
            ret+=siz[son[cur][0]];
            splay(cur,0); return ret;
        } if(val[cur]>x)
        cur=son[cur][0];
        else
        ret+=siz[son[cur][0]]+cnt[cur],
        cur=son[cur][1];
    } return ret;
}

然后这是过了原版的另一个函数:

inline int getrnk(int x)
{
    find(x);
    return siz[son[root][0]];
}

其中find(x)如下:

//ri : register int
inline void find(int x){
    ri cur=root;
    while(son[cur][val[cur]<x]&&val[cur]!=x)
    cur=son[cur][val[cur]<x];
    splay(cur,0);
}
//val:点值
//son:两个儿子
//splay(x,tar):把x伸展成tar的儿子

第二个是教练上课讲的版本,因为它又短又能用所以今天一直用的这个(
然后在这里疯狂WA 30pts有10+次
然后我气急败坏翻了很久讨论区发现这里说应该写成原来那样(第一个版本)
¿
求解答


by Neutralized @ 2022-02-08 20:28:42

换成原来的版本就A了(((


by Gokix @ 2022-02-08 20:44:46

@Neutralized

你得看 getrank 的那个值在不在 Splay 里


by Gokix @ 2022-02-08 20:47:18

第一个方法是在不在都行

第二个方法必须保证 x 在 Splay 中

仔细看的话数据加强版并不保证 x 在 Splay 中,所以不能用第二个方法

by Gokix @ 2022-02-08 20:49:39

但是一般用 Splay 的时候都保证 getrank 的数在 Splay 里

by Gokix @ 2022-02-08 20:50:42

而且就算是 x 不在 Splay 中,你也可以先把它插入,查排名之后再删除

三行解决(

by Neutralized @ 2022-02-08 21:01:23

@Gokix 抱歉刚刚才看到
非常感谢 刚才脑子抽一下还准备找您再问问 反应过来了(

刚才试了下,第二种雀实可以改成

inline int getrnk(int x){
    insert(x);
    ri ret=siz[son[root][0]];
    erase(x); return ret;
}

,只不过会慢一点
已关注


by Gokix @ 2022-02-08 21:07:51

@Neutralized

啊啦啊啦,你写 Splay 竟然还关注常数(((

确实会慢,毕竟要多加点删点,你可以挑一种你喜欢的写


by Neutralized @ 2022-02-08 21:32:47

@Gokix 草 kurumi经典词语

因为经常偷偷淦一些阴间算法不会正解所以卡常都卡成习惯了(


|