splay过不了样例求助

P3391 【模板】文艺平衡树

Xqbk @ 2021-05-19 20:54:39

现象是节点的son没有成功连接到被翻转的子树(?)

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=100005;
const int INF=1e9;
int n,m;
int rt,tot;
struct Splay
{
    int fa,son[2],siz,cnt,val,rev;
}s[MAXN];
void pushup(int x)
{
    s[x].siz=s[s[x].son[0]].siz+s[s[x].son[1]].siz+s[x].cnt;
}
void pushdown(int x)
{
    if(x&&s[x].rev)
    {
        s[s[x].son[0]].rev^=1;
        s[s[x].son[1]].rev^=1;
        swap(s[s[x].son[0]],s[s[x].son[1]]);
        s[x].rev=0;
    }
}
bool get(int x)
{
    return x==s[s[x].fa].son[1];
}
void rotate(int x)
{
    int y=s[x].fa;
    int z=s[y].fa;
    pushdown(x);
    pushdown(y);
    int d=get(x);
    s[y].son[d]=s[x].son[d^1];
    if(s[x].son[d^1])s[s[x].son[d^1]].fa=y;
    s[x].son[d^1]=y;
    s[y].fa=x;
    s[x].fa=z;
    if(z)s[z].son[y==s[z].son[1]]=x;
    pushup(y);
    pushup(x);
}
void splay(int x,int k)
{
    for(int f=s[x].fa;f=s[x].fa,f!=k;rotate(x))
    {
        if(s[f].fa!=k)rotate(get(x)==get(f)?f:x);
    }
    if(!k)
    {
        rt=x;
    }
}
void ins(int k)
{
    if(!rt)
    {
        s[++tot].val=k;
        s[tot].cnt++;
        rt=tot;
        pushup(rt);
        return;
    }
    int cur=rt;
    int f=0;
    while(1)
    {
        if(s[cur].val==k)
        {
            s[cur].cnt++;
            pushup(cur);
            pushup(f);
            splay(cur,0);
            break;
        }
        f=cur;
        cur=s[cur].son[s[cur].val<k];
        if(!cur)
        {
            s[++tot].val=k;
            s[tot].cnt++;
            s[tot].fa=f;
            s[f].son[s[f].val<k]=tot;
            pushup(tot);
            pushup(f);
            splay(tot,0);
            break;
        }
    }
}
int find(int k)
{
    int cur=rt;
    while(1)
    {
        pushdown(cur);
        if(s[cur].son[0]&&k<=s[s[cur].son[0]].siz)
        {
            cur=s[cur].son[0];
        }
        else
        {
            k-=s[cur].cnt+s[s[cur].son[0]].siz;
            if(k<=0)
            {
                splay(cur,0);
                return cur;
            }
            cur=s[cur].son[1];

        }
    }
}
void dfs(int cur)
{
    pushdown(cur);
    if(s[cur].son[0])
    {
        dfs(s[cur].son[0]);
    }
    if(s[cur].val!=INF&&s[cur].val!=-INF)
    {
        cout<<s[cur].val<<' ';
    }
    if(s[cur].son[1])
    {
        dfs(s[cur].son[1]);
    }
    return;
}
void reverse(int l,int r)
{
    int x=find(l-1);
    int y=find(r+1);
    splay(x,0);
    splay(y,x);
    int cur=s[rt].son[1];
    cur=s[cur].son[0];
    s[cur].rev^=1;
}
int main()
{
    cin>>n>>m;
    ins(-INF);
    ins(INF);
    for(int i=1;i<=n;i++)
    {
        ins(i);
    }
    for(int i=1;i<=m;i++)
    {
        int l,r;
        cin>>l>>r;
        reverse(l+1,r+1);
    }
    dfs(rt);
}

by 阿丑 @ 2021-05-19 21:31:09

@Xqbk 好像把 pushdown 里的 swap(s[s[x].son[0]],s[s[x].son[1]]); 写成 swap(s[x].son[0],s[x].son[1]); 就能过样例了,但我不知道为什么


by 阿丑 @ 2021-05-19 21:37:52

哦,如果 swaps[0] 换成有权值的节点的话就会出现非常灵异的现象。

另,我感觉为了确保复杂度正确,应该在 splay 里先 pushdown 吧,不然的话方向应该不确定。


by Xqbk @ 2021-05-20 21:25:50

@阿丑 感谢,过了

但是测试了一下splay里面有没有pushdown好像没发现区别


|