关于 UB

P3391 【模板】文艺平衡树

Zxx200611 @ 2022-03-24 11:16:13

第一组数据,我的代码在本地 0ms,但在洛谷上或是 CF 的 Custom Test 均 TLE。
求助,调了一早上了:

#include<bits/stdc++.h>
using namespace std;

struct Splay
{
    struct Node
    {
        int ch[2],fth,siz;
        int val,cnt;
        bool tag;
    };
    vector<Node> t;
    int rt;

    inline
    int newNode(int _fth,int _siz,int _val,int _cnt,bool _tag)
    {
        t.push_back((Node){{-1,-1},_fth,_siz,_val,_cnt,_tag});
        return t.size()-1;
    }
    inline
    void pushUp(int u)
    {
        t[u].siz=(t[u].ch[0]==-1?0:t[t[u].ch[0]].siz)+(t[u].ch[1]==-1?0:t[t[u].ch[1]].siz)+t[u].cnt;
    }
    inline
    void pushDown(int u)
    {
        if(t[u].tag==1)
        {
            if(t[u].ch[0]!=-1) swap(t[t[u].ch[0]].ch[0],t[t[u].ch[0]].ch[1]),t[t[u].ch[0]].tag^=1;
            if(t[u].ch[1]!=-1) swap(t[t[u].ch[1]].ch[0],t[t[u].ch[1]].ch[1]),t[t[u].ch[1]].tag^=1;
            t[u].tag=0;
        }
    }
    inline
    int recognize(int u)
    {
        return (t[u].fth==-1?0:(u!=t[t[u].fth].ch[0]));
    }
    inline
    void rotate(int u)
    {
        int v=t[u].fth,w=t[v].fth;
        pushDown(v),pushDown(u);
        int id=recognize(u);
        if(t[u].ch[!id]!=-1)
        {
            t[t[u].ch[!id]].fth=v;
        }
        t[v].ch[id]=t[u].ch[!id];
        t[u].fth=w;
        if(w!=-1)
        {
            t[w].ch[recognize(v)]=u;
        }
        t[v].fth=u,t[u].ch[!id]=v;
        pushUp(v),pushUp(u);
    }
    inline
    void splay(int u,int aim)
    {
        while(t[u].fth!=aim)
        {
            int v=t[u].fth;
            if(t[v].fth==aim)
            {
                rotate(u);
            }
            else
            {
                if(recognize(u)!=recognize(v))
                {
                    rotate(u),rotate(u);
                }
                else
                {
                    rotate(v),rotate(u);
                }
            }
        }
        if(aim==-1)
        {
            rt=u;
        }
    }
    inline
    int buildTree(vector<int> &s)
    {
        int u=newNode(-1,1,s[s.size()/2],1,0);
        vector<int> sl(0),sr(0);
        for(int i=0;i<s.size()/2;i++)
        {
            sl.push_back(s[i]);
        }
        for(int i=s.size()/2+1;i<s.size();i++)
        {
            sr.push_back(s[i]);
        }

        int v1=-1,v2=-1;
        if(sl.size()>=1) v1=buildTree(sl);
        if(sr.size()>=1) v2=buildTree(sr);

        t[u].ch[0]=v1,t[u].ch[1]=v2;
        if(v1!=-1) t[v1].fth=u;
        if(v2!=-1) t[v2].fth=u;
        pushUp(u);
        return u;
    }
    inline
    int getPos(int rak)
    {
        int u=rt;
        while(1)
        {
            pushDown(u);
            int lsz=t[u].ch[0]==-1?0:t[t[u].ch[0]].siz;
            if(lsz+1<=rak&&lsz+t[u].cnt>=rak)
            {
                return u;
            }
            else if(lsz+t[u].cnt<rak)
            {
                rak-=t[t[u].ch[0]].siz+t[u].cnt,u=t[u].ch[1];
            }
            else
            {
                u=t[u].ch[0];
            }
        }
        return -1;
    }
    inline
    void flipInterval(int l,int r)
    {
        int u=getPos(l-1),v=getPos(r+1),w;
        splay(u,-1),splay(v,u),w=t[v].ch[0];
        t[w].tag^=1,swap(t[w].ch[0],t[w].ch[1]);
    }
    inline
    vector<int> getAns(int u)
    {
        vector<int> res(0),tmp(0);
        pushDown(u);
        if(t[u].ch[0]!=-1)
        {
            tmp=getAns(t[u].ch[0]);
            res.insert(res.end(),tmp.begin(),tmp.end());
        }
        res.push_back(t[u].val);
        if(t[u].ch[1]!=-1)
        {
            tmp=getAns(t[u].ch[1]);
            res.insert(res.end(),tmp.begin(),tmp.end());
        }
        return res;
    }
};
Splay st;

int main()
{
    int n,q;
    cin>>n>>q;

    vector<int> s(n+2);
    for(int i=0;i<=n+1;i++)
    {
        s[i]=i;
    }
    st.rt=st.buildTree(s);

    while(q--)
    {
        int l,r;
        cin>>l>>r;
        st.flipInterval(l+1,r+1);
    }

    vector<int> res=st.getAns(st.rt);
    for(int i=1;i<=n;i++)
    {
        cout<<res[i]<<" ";
    }
    cout<<endl;
}

by rxjdasiwzl @ 2022-03-24 11:32:26

@Zxx200611 t[u].ch[0] == -1 的时候,进入 else if (lsz + t[u].cnt < rak),然后你应该减去 lsz 而不是 t[t[u].ch[0]].siz


by sw2022 @ 2022-03-24 12:15:59

@Zxx200611 UB不是这么用的吧,UB跟TLE又没关系,UB只会导致CE


by Zxx200611 @ 2022-03-24 12:50:57

@rxjdasiwzl THX!


by rxjdasiwzl @ 2022-03-24 12:58:31

@sw2022_ 数组越界属于 UB,UB 不会导致 CE,但是可以导致 WA RE TLE 等任何情况。


by sw2022 @ 2022-03-24 13:00:15

@rxjdasiwzl az没看出来越界了。。。原来有个t[-1]....


|