求求了解决一下孩子的疑惑

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

阿噫齐贝林 @ 2022-09-13 17:48:48

为啥fhq treap建树的规模会影响结果

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-48;c=getchar();}
    return x*f;
}
const int N=1000005;
int rt,num;
int n,m;
int last=0,ans=0;
struct treap{
    int val,rand,ls,rs,size;
}tr[N];
inline int New(int val)
{
    tr[++num].val=val;
    tr[num].rand=rand();
    tr[num].ls=0,tr[num].rs=0;
    tr[num].size=1;
    return num;
}
inline void Update(int p)
{
    tr[p].size =tr[tr[p].ls].size +tr[tr[p].rs].size +1;
}
inline void Split(int p,int val,int &x,int &y)
{
    if(!p){x=0,y=0;return;}
    if(tr[p].val<=val){x=p;Split(tr[p].rs,val,tr[p].rs,y);}
    else{y=p;Split(tr[p].ls,val,x,tr[p].ls);}
    Update(p);
}
inline int Merge(int x,int y)
{
    if(!x||!y) return x+y;
    if(tr[x].rand<tr[y].rand)
    {
        tr[x].rs=Merge(tr[x].rs,y);
        Update(x);
        return x;
    }
    else
    {
        tr[y].ls=Merge(x,tr[y].ls);
        Update(y);
        return y;
    }
}
inline void insert(int val)
{
    int x,y;
    Split(rt,val-1,x,y);
    rt=Merge(Merge(x,New(val)),y);
} 
inline void Delete(int val)
{
    int x,y,z;
    Split(rt,val,x,z);
    Split(x,val-1,x,y);
    rt=Merge(Merge(x,Merge(tr[y].ls,tr[y].rs)),z);
} 
inline int rnk(int val)
{
    int x,y,ass;
    Split(rt,val-1,x,y);
    ass=tr[x].size+1;
    rt=Merge(x,y);
    return ass;
}
inline int Find(int p,int Kth)
{
    if(Kth==tr[tr[p].ls].size+1) return p;
    if(Kth<=tr[tr[p].ls].size) return Find(tr[p].ls,Kth);
    return Find(tr[p].rs,Kth-tr[tr[p].ls].size-1);
}
inline int pre(int val)
{
    int x,y,ass;
    Split(rt,val-1,x,y);
    ass=tr[Find(x,tr[x].size)].val;
    rt=Merge(x,y);
    return ass;
}
inline int nxt(int val)
{
    int x,y,ass;
    Split(rt,val,x,y);
    ass=tr[Find(y,1)].val;
    rt=Merge(x,y);
    return ass;
}
signed main()
{
    srand(time(0));
    n=read(),m=read();
    int val,op;
    for(int i=1;i<=n;i++)
    {
        val=read();
        insert(val);
    }
    for(int i=1;i<= m;i++)
    {
        op=read(),val=read();
        val^=last;
        if(op==1)insert(val);
        if(op==2)Delete(val);
        if(op==3)
        {
            last=rnk(val);
            ans^=last;
        }
        if(op==4)
        {
            last=tr[Find(rt,val)].val;
            ans^=last;
        }
        if(op==5)
        {
            last=pre(val);
            ans^=last;
        }
        if(op==6)
        {
            last=nxt(val);
            ans^=last;
        }
    }
    printf("%d",ans);
}

tr[N](N=1000005)是92分

tr[2*N]能AC

题解大佬写的是tr[2*N]但我不知道为啥,或者有大佬能解释一下建树的范围有啥要注意的吗


by 鏡音リン @ 2022-09-13 17:52:05

@阿噫齐贝林 其实N+M就行吧……

本来有1e5个点,有1e6次插入操作,所以是1100000……


by COsm0s @ 2022-09-13 18:15:48

管理楼下,且楼上正解


by 阿噫齐贝林 @ 2022-09-14 17:00:59

@鏡音リン orz懂了懂了谢谢管理员大爷


|