萌新初学Splay,样例都wa,求调(提供建议的都给关注QAQ)谢谢

P3391 【模板】文艺平衡树

Wsy_flying_forever @ 2022-02-09 21:42:30

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,m,tot;
int root;
struct Splay{
    int l,r;
    int val;
    int siz;
    int fa;
    int vis=-1;
    #define l(x) tree[x].l
    #define r(x) tree[x].r
    #define val(x) tree[x].val
    #define siz(x) tree[x].siz
    #define fa(x) tree[x].fa
    #define vis(x) tree[x].vis
} tree[maxn];
int Inf=2e9;
int pos[maxn];
void update(int p){
    siz(p)=siz(l(p))+siz(r(p))+1;
}
int New(int val,int fa){
    val(++tot)=val;
    siz(tot)=1;
    fa(tot)=fa;
    if (val!=0 && val!=n+1) vis(tot)=0;
    return tot;
}
void build(){
    New(0,0),New(n+1,1);
    root=1,r(1)=2;
    update(root);
}
void zig(int &p){
    int q=l(p);
    l(p)=r(q),r(q)=p,p=q;
    update(r(p));update(p);
}
void zag(int &p){
    int q=r(p);
    r(p)=l(q),l(q)=p,p=q;
    update(l(p));update(p);
}
void Splay(int x,int target){
    if (fa(x)==target) return ;
    int y=fa(x),w=fa(y);
    if (w==target){
        if (l(y)==x) zig(y);
        else zag(y);
        return ;
    }
    if (l(w)==y && l(y)==x){
        zig(w),zig(y);
        return ;
    }
    if (r(w)==y && r(y)==x){
        zag(w),zag(y);
        return ;
    }
    if (l(w)==y && r(y)==x){
        zag(y),zig(w);
        return ;
    }
    if (r(w)==y && l(y)==x){
        zig(y),zag(w);
        return ;
    }
}
void Insert(int val){
    int x=root,fa=0,dir=0;
    while (x){
        ++siz(fa=x);
        if (val<val(x)) dir=0,x=l(x);
        else dir=1,x=r(x);
    }
    x=New(val,fa);
    Splay(x,0);
}
void spread(int p){
    if (p && pos[p]){
        pos[l(p)]^=1;
        pos[r(p)]^=1;
        swap(l(p),r(p));
        pos[p]=0;
    }
}
int Find(int Rank){
    int x=root;
    while (x){
        spread(x);
        if (Rank<=siz(l(x))) x=l(x);
        else {
            Rank-=siz(l(x))+1;
            if (!Rank) return x;
            x=r(x);
        }
    }
}
void dfs(int p){
    spread(p);
    if (val(l(p))) dfs(l(p));
    if (vis(p)!=-1) printf("%d ",val(p));
    if (val(r(p))) dfs(r(p)); 
}
int main(){
    scanf("%d%d",&n,&m);
    build();
    for (int i=1;i<=n;i++)
      Insert(i);
    for (int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        x=Find(x-1);
        y=Find(y+1);
        Splay(x,0);
        Splay(y,x);
        pos[l(r(root))]^=1;
    }
    dfs(root);
    return 0;
}

by bruhify @ 2022-02-09 22:18:29

Splay函数只做了一次双旋


by Wsy_flying_forever @ 2022-02-09 22:44:00

@bruhify 谢谢大佬,我加上双旋并且还将insert里父子关系补充修正,可还是不对【流汗】


by Wsy_flying_forever @ 2022-02-09 22:44:37

若能完整帮我改对,则感激不尽


by bruhify @ 2022-02-10 12:21:57

@魏思远 能把您现在的代码私信发一下吗/kk


|