求调,带父指针splay大红大紫,写法类似OIwiki

P3391 【模板】文艺平衡树

GameFreak @ 2023-01-12 23:30:51

RT,带父的指针 splay,RE 了,而且 luogu 的样例 WA 但我们学校的水样例过了

随手打了个随机数跑了五六次操作就挂了,也是 RE。数据我忘了存,不过很好构造。我当时以为 114514 的长度 +17 个随机区间不能造出来,然后惊奇地发现 RE 了。

有两个 splay,一个是 OIwiki 上那种直接旋到根的,另一个是自己写的,仿照 OIwiki 的做法旋到指定节点。其他部分过了平衡树板子题,大概率就是自己写的这个 splay 挂了。

代码(不要嫌弃马蜂QAQ):

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//static char buf[1000000],*p1=buf,*p2=buf,obuf[1000000],*p3=obuf;
//#define flush() fwrite(obuf,p3-obuf,1,stdout)
//#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
//#define putchar(x) (p3-obuf<1000000)?(*p3++=x):(flush(),p3=obuf,*p3++=x)
template<typename T> inline void read(T&);
template<typename T> inline void write(T);
template<typename... Args> inline void read(Args& ...);
template<typename... Args> inline void write(Args ...);
inline void read(char*);
inline void read(char&);
inline void read(string&);
inline void write(char);
inline void write(char*);
inline void write(const char*);
int n,m;
template<typename T=int> class Splay{
private:
    struct node{
        bool tag;
        T val;
        int cnt,siz;
        node* fa;
        node* ch[2];
        node():tag(0),val(),cnt(0),siz(0),fa(nullptr){ch[0]=ch[1]=nullptr;}
        node(T Val):tag(0),val(Val),cnt(1),siz(1),fa(nullptr){ch[0]=ch[1]=nullptr;}
        node(T Val,node* Fa):tag(0),val(Val),cnt(1),siz(1),fa(Fa){ch[0]=ch[1]=nullptr;}
    };
    int get_siz(node* p){return p==nullptr?0:p->siz;}
    int get_cnt(node* p){return p==nullptr?0:p->cnt;}
    T get_val(node* p){return p==nullptr?0:p->val;}
    node* root;
    void updata(node* p){if(p) p->siz=get_siz(p->ch[0])+get_siz(p->ch[1])+get_cnt(p);}
    void push_down(node* p){
        if((!p)||(!(p->tag))) return;
        if(p->ch[0]) (p->ch[0])->tag^=1;
        if(p->ch[1]) (p->ch[1])->tag^=1;
        swap(p->ch[0],p->ch[1]);
        p->tag=0;
    }
    bool check(node* p){return p==(p->fa)->ch[1];}
    void clear(node* p){
        if(p) delete p;
        p=nullptr;
    }
    void rotate(node* p){
        node *fa=p->fa,*gra=fa->fa;
        bool chk=check(p);
        push_down(p),push_down(fa);
        fa->ch[chk]=p->ch[chk^1];
        if(p->ch[chk^1]) (p->ch[chk^1])->fa=fa;
        p->ch[chk^1]=fa,fa->fa=p,p->fa=gra;
        if(gra) gra->ch[fa==(gra->ch[1])]=p;
        updata(p),updata(fa);
    }
    node* kth(int rnk){
        node* p=root;
        while(1){
            push_down(p);
            if(p->ch[0]&&rnk<=get_siz(p->ch[0])) p=p->ch[0];
            else{
                rnk-=get_cnt(p)+get_siz(p->ch[0]);
                if(rnk<=0) return splay(p),p;
                else p=p->ch[1];
            }
        }
    }
public:
    Splay():root(nullptr){}
    node* pre(){
        node* p=root->ch[0];
        if(!p) return p;
        while(p->ch[1]) p=p->ch[1];
        return splay(p),p;
    }
    node* nxt(){
        node* p=root->ch[1];
        if(!p) return p;
        while(p->ch[0]) p=p->ch[0];
        return splay(p),p;
    }
//  void splay(node* p,node* rt){
//      for(node* fa=p->fa;(fa=p->fa)==rt;rotate(p)) if(fa->fa) rotate(check(p)==check(fa)?fa:p);
////        root=p;
//  }
    void splay(node* p,node* rt){
//      out();
//      printf("%p %p %p\n",p->fa,rt->ch[0],rt->ch[1]);
        node* q=p->fa;
//      if(q) printf("%p %p\n",q->fa,rt);
        for(node* fa=p->fa;(fa=p->fa)&&fa!=rt->fa;rotate(p)) if(fa->fa!=rt->fa) /*cout<<"zhouji\n",*/rotate(check(p)==check(fa)?fa:p);
        if(rt==root) root=p;
    }
    void splay(node* p){
        push_down(p);
        for(node* fa=p->fa;(fa=p->fa);rotate(p)){
            if(fa->fa) rotate(check(p)==check(fa)?fa:p);
        }
        root=p;
    }
    void insert(T val){
        if(!root){
            root=new node(val);
            updata(root);
            return;
        }
        node *p=root,*fa=nullptr;
        while(1){
            if(p->val==val){
                p->cnt++;
                updata(p),updata(fa);
                splay(p);
                break;
            }
            fa=p;
            p=p->ch[p->val<val];
            if(!p){
                p=new node(val,fa);
                fa->ch[fa->val<val]=p;
                updata(p),updata(fa);
                splay(p);
                break;
            }
        }
    }
    void erase(T val){
        get_rank(val);
        if(get_cnt(root)>1){
            root->cnt--;
            updata(root);
            return;
        }
        if(!root->ch[0]&&!root->ch[1]){
            clear(root);
            root=nullptr;
            return;
        }
        if(!root->ch[0]){
            node* p=root;
            root=root->ch[1],root->fa=nullptr;
            clear(p);
            return;
        }
        if(!root->ch[1]){
            node* p=root;
            root=root->ch[0],root->fa=nullptr;
            clear(p);
            return;
        }
        node *p=root,*pr=pre();
        (p->ch[1])->fa=pr;
        pr->ch[1]=p->ch[1];
        clear(p),updata(root);
    }
    int get_rank(T val){
        int ret=0;
        node* p=root;
        while(1){
            if(val<p->val) p=p->ch[0];
            else{
                ret+=get_siz(p->ch[0]);
                if(val==p->val) return splay(p),ret+1;
                else ret+=get_cnt(p),p=p->ch[1];
            }
        }
    }
    T k_th(int rnk){
        node* p=root;
        while(1){
            push_down(p);
            if(p->ch[0]&&rnk<=get_siz(p->ch[0])) p=p->ch[0];
            else{
                rnk-=get_cnt(p)+get_siz(p->ch[0]);
                if(rnk<=0) return splay(p),p->val;
                else p=p->ch[1];
            }
        }
    }
    T get_pre(T val){
        insert(val);
        T ret=get_val(pre());
        erase(val);
        return ret;
    }
    T get_nxt(T val){
        insert(val);
        T ret=get_val(nxt());
        erase(val);
        return ret;
    }
    void reverse(int L,int R){
        node *l=kth(L),*r=kth(R+1);
//      write(l->val,' ',r->val,'\n');
        splay(r);
        splay(l);
//      out();
//      cout<<endl;
//      write("zhouji\n");
//      splay(r,root->ch[1]);
        node *p=(root->ch[1]);
//      out();
//      printf("%d %p\n",p->val,p);
        p=p->ch[0];
//      printf("%p\n",p);
//      printf("%d\n",root->val);
        p->tag^=1;
//      write("zhouya\n");
//      printf("%d\n",root->val);
    }
    void print(node* p){
        if(!p) return;
        push_down(p);
        print(p->ch[0]);
        if((p->val)>=1&&(p->val)<=n) write((p->val),' ');
        print(p->ch[1]);
    }
    void print(){print(root);}
    void out(node* p){
        if(!p) return;
        cout<<(p->val)<<":"<<"("<<((p->ch[0])?(p->ch[0])->val:-1)<<","<<((p->ch[1])?(p->ch[1])->val:-1)<<")\n";
        out(p->ch[0]),out(p->ch[1]);
    }
    void out(){out(root);}
};
Splay<int> tr;
signed main(){
//  freopen("2.txt","r",stdin);
    read(n,m);
    tr.insert(0),tr.insert(n+1);
    for(int i=1;i<=n;i++) tr.insert(i);
    for(int l,r;m--;) read(l,r)/*,cout<<l<<" "<<r<<"\n"*/,tr.reverse(l,r+1);//,tr.print(),cout<<endl;
    tr.print();
//  flush();
    return 0; 
}

template<typename T> inline void read(T& x){
    x=0;bool flag=0;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') flag=1;
    if(flag) for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)-(ch&15);
    else for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch&15);
}
template<typename T> inline void write(T x){
    static int sta[40];
    int top=0;
    if(x<0){
        putchar('-');
        do sta[top++]=(-x)%10,x/=10;
        while(x);
    }
    else{
        do sta[top++]=x%10,x/=10;
        while(x);
    }
    while(top) putchar(sta[--top]^48);
}
inline void write(char x){putchar(x);}
inline void read(char& c){while((c=getchar())==' '||c=='\n');}
inline void read(string& str){
    char ch;
    str="";
    while((ch=getchar())==' '||ch=='\n');
    str+=ch;
    while((ch=getchar())!=' '&&ch!='\n') str+=ch;
}
inline void read(char* str){
    while((*str=getchar())==' '||*str=='\n');
    while((*++str=getchar())!=' '&&*str!='\n');
    *str=0;
}
inline void write(char* str){while(*str!='\0') putchar(*str++);}
inline void write(const char* str){while(*str!='\0') putchar(*str++);}
template<typename... Args> inline void read(Args& ...args){(void)initializer_list<int>{(read(args),0)...};}
template<typename... Args> inline void write(Args ...args){(void)initializer_list<int>{(write(args),0)...};}

by GameFreak @ 2023-01-13 09:09:04

调出了,splay改成了这样:

    void splay(node* p){
        for(node* fa=p->fa;(fa=p->fa);rotate(p)) if(fa->fa) rotate(check(p)==check(fa)?fa:p);
        root=p;
    }

|