这题卡Splay吗。。。萌新刚学OI 50pts求助

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

谦谦君子 @ 2020-02-27 22:17:20

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000005;
int n,m,root,cnt,ans,last;
int father[maxn],val[maxn],son[maxn][2],sum[maxn],size[maxn];
int read()
{
    int s=0,f=1;
    char ch=getchar();
    while (!isdigit(ch))
    {
        if (ch==45)
        {
            f=-1;
        }
        ch=getchar();
    }
    while (ch>='0'&&ch<='9')
    {
        s=s*10+ch-'0';
        ch=getchar();
    }
    return s*f;
}
void clear(int x)
{
    father[x]=son[x][0]=son[x][1]=val[x]=size[x]=sum[x]=0;
    return ;
}
int get(int x)
{
    return son[father[x]][1]==x;
}
void update(int x)
{
    if (x!=0)
    {
        size[x]=sum[x];
        if (son[x][0])
        {
            size[x]+=size[son[x][0]];
        }
        if (son[x][1])
        {
            size[x]+=size[son[x][1]];
        }
    }
    return ;
}
void connect(int x,int y,int z)
{
    if (x)
    {
        father[x]=y;
    }
    if (y)
    {
        son[y][z]=x;
    }
    return ;
}
void rotate(int x)
{
    int fa=father[x],ffa=father[fa],m=get(x),n=get(fa);
    connect(son[x][m^1],fa,m);
    connect(fa,x,m^1);
    connect(x,ffa,n);
    update(fa);
    update(x);
}
void splay(int x)
{
    for (int fa;fa=father[x];rotate(x))
    {
        if (father[fa])
        {
            if (get(x)==get(fa))
            {
                rotate(fa);
            }
            else
            {
                rotate(x);
            }
        }
    }
    root=x;
    return ;
}
void insert(int x)
{
    if (root==0)
    {
        root=++cnt;
        val[root]=x;
        size[root]=sum[root]=1;
        son[root][0]=son[root][1]=0;
        return ;
    }
    int now=root,fa=0;
    while (1)
    {
        if (val[now]==x)
        {
            sum[now]++;
            update(now);
            update(fa);
            splay(now);
            return ;
        }
        fa=now,now=son[now][x>val[now]];
        if (now==0)
        {
            cnt++;
            val[cnt]=x;
            size[cnt]=sum[cnt]=1;
            father[cnt]=fa;
            son[fa][x>val[fa]]=cnt;
            update(fa);
            splay(cnt);
            return ;
        }
    }
}
int find_rank(int x)
{
    int now=root,ans=0;
    while (1)
    {
        if (x<val[now])
        {
            now=son[now][0];
            continue;
        }
        ans+=size[son[now][0]];
        if (x==val[now])
        {
            splay(now);
            return ans+1;
        }
        ans+=sum[now];
        now=son[now][1];
    }
}
int find_num(int x)
{
    int now=root;
    while (1)
    {
        if (son[now][0]&&x<=size[son[now][0]])
        {
            now=son[now][0];
            continue;
        }
        if (son[now][0])
        {
            x-=size[son[now][0]];
        }
        if (x<=sum[now])
        {
            splay(now);
            return val[now];
        }
        x-=sum[now];
        now=son[now][1];
    }
}
int pre()
{
    int now=son[root][0];
    while (son[now][1])
    {
        now=son[now][1];
    }
    return now;
}
int suf()
{
    int now=son[root][1];
    while (son[now][0])
    {
        now=son[now][0];
    }
    return now;
}

inline void del(int x)
{
    find_rank(x);
    if (sum[root]>1)
    {
        sum[root]-=1;
        update(root);
        return ;
    }
    if (son[root][0]==0&&son[root][1]==0)
    {
        clear(root);
        root=0;
        return ;
    }
    if (son[root][0]==0)
    {
        int tmp=root;
        father[root=son[root][1]]=0;
        clear(tmp);
        return ;
    }
    if (son[root][1]==0)
    {
        int tmp=root;
        father[root=son[root][0]]=0;
        clear(tmp);
        return ;
    }
    int tmp=root,Pre=pre();
    splay(Pre);
    connect(son[tmp][1],root,1);
    clear(tmp);
    update(root);
    return ;
}

int main()
{
    n=read(),m=read();
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        int x=read();
        insert(x);
    }
    while (m--)
    {
        int opt,k;
        opt=read(),k=read();
        k^=last;
        if ( opt==1)
        {
            insert(k);
        }
        if (opt==2)
        {
            del(k);
        }
        if (opt==3)
        {
            insert(k);
            last=find_rank(k);
            del(k);
            ans^=last;
        }
        if (opt==4)
        {
            last=find_num(k);
            ans^=last;
        }
        if (opt==5)
        {
            insert(k);
            last=val[pre()];
            ans^=last;
            del(k);
        }
        if (opt==6)
        {
            insert(k);
            last=val[suf()];
            ans^=last;
            del(k);
        }
    }
    cout<<ans<<"\n";
    return 0;
}

by Smile_Cindy @ 2020-02-27 22:22:02

@谦谦君子

开O2

为啥你们的erase都写得这么麻烦?

我的erase

void erase(int x)
{
    int pre=prev(x),nxt=next(x);
    splay(pre);
    splay(nxt,pre);
    int t=ch[nxt][0];
    if(cnt[t]>1)
    {
        cnt[t]--;
        splay(t);
    }
    else ch[nxt][0]=0;
}

by 1kri @ 2020-02-27 22:25:46

这么友好毒瘤的数据fhq-treap是没救了吗


by Froggy @ 2020-02-27 22:32:26

@L_C_A

不开O2最慢点还不到1.2s呢

by 1kri @ 2020-02-27 22:33:26

@Froggy 真的,辣我再码一遍,谢谢


by gyh20 @ 2020-02-27 22:43:14

这道题应该不卡,我之前过不了是写错了


by Skyjoy @ 2020-02-27 22:44:48

qndmx


by Polaris_Dane @ 2020-02-27 22:53:33

不卡,我6s多过了


by Minecraft万岁 @ 2020-02-27 23:00:17

Splay跑起来应该很快啊


by 谦谦君子 @ 2020-02-28 21:27:33

@Froggy 我已经用fhqA了qaq,只是发现Splay过不了,但是其实splay效率也还不错吧


by 谦谦君子 @ 2020-02-28 21:28:15

@L_C_A fhq可以过啊qaq


|