平衡树点分裂
关于\(\tt{FHQ}\)平衡树点分裂的写法
前言:最近感觉不怎么想写平衡树了,然后今天发现仅有的会写的三种平衡树(\(FHQtreap,splay,Scapegoat \ Tree\)),基本上只会打\(FHQ\)了(这个东西真的太好打了
不过\(\tt{NOIp}\)还是复习一下,虽然常数比较大所以我一定会优先考虑线段树的
今天回去打了一下列队,决定统一一下自己点分裂的写法
一般来说,点分裂时,平衡树每个点都代表一段区间\([l,r]\)
当需要区间分裂的时候,我们不妨就在\(\tt{split}\)的里面进行分裂
#define siznow (segr[now]+1-segl[now])
void split(int now,int k,int &x,int &y)
{
if(!now) {x=y=0;return;}
if(siz[ls]>=k)
y=now,split(ls,k,x,ls),updata(y);
else if(k>=siznow+siz[ls])
x=now,split(rs,k-siznow-siz[ls],rs,y),updata(x);
else
{
ll p=k-siz[ls]+segl[now]-1;
x=Merge(ch[now][0],New(segl[now],p));
y=Merge(New(p+1,segr[now]),ch[now][1]);
}
}
恩,感觉还是蛮方便的,以后就这么写了
列队的完整代码
#include <cstdio>
#include <cstdlib>
#define ls ch[now][0]
#define rs ch[now][1]
#define ll long long
const int N=2400000;
int ch[N][2],val[N],root[N],tot,q;
ll segl[N],segr[N],siz[N],n,m;
#define siznow (segr[now]-segl[now]+1)
void updata(int now){siz[now]=siz[ls]+siz[rs]+siznow;}
int Merge(int x,int y)
{
if(!x||!y) return x+y;
if(val[x]<val[y])
{
ch[x][1]=Merge(ch[x][1],y);
updata(x);
return x;
}
else
{
ch[y][0]=Merge(x,ch[y][0]);
updata(y);
return y;
}
}
int New(ll l,ll r)
{
if(l>r) return 0;
siz[++tot]=r+1-l,val[tot]=rand(),segl[tot]=l,segr[tot]=r;
return tot;
}
void split(int now,int k,int &x,int &y)
{
if(!now) {x=y=0;return;}
if(siz[ls]>=k)
y=now,split(ls,k,x,ls),updata(y);
else if(k>=siznow+siz[ls])
x=now,split(rs,k-siznow-siz[ls],rs,y),updata(x);
else
{
ll p=k-siz[ls]+segl[now]-1;
x=Merge(ch[now][0],New(segl[now],p));
y=Merge(New(p+1,segr[now]),ch[now][1]);
}
}
void Insert(int id,ll p,ll d)
{
int x,y;
split(root[id],p,x,y);
root[id]=Merge(x,Merge(New(d,d),y));
}
ll query(int id,ll p)
{
int x,y,z;
split(root[id],p,x,y);
split(x,p-1,x,z);
ll ret=segl[z];
root[id]=Merge(x,y);
return ret;
}
int main()
{
scanf("%lld%lld%d",&n,&m,&q);
for(ll i=1;i<=n;i++)
{
Insert(n+1,i,i*m);
root[i]=New(1+(i-1)*m,i*m-1);
}
ll ans,rig;
for(int x,y,i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
if(y==m)
{
ans=query(n+1,x);
Insert(n+1,n,ans);
}
else
{
ans=query(x,y);
rig=query(n+1,x);
Insert(n+1,n,ans);
Insert(x,m-1,rig);
}
printf("%lld\n",ans);
}
return 0;
}
2018.11.6