Luogu3380 【模板】二逼平衡树(树套树)
Luogu3380 【模板】二逼平衡树(树套树)
两年没写树套树了,今天写了一发线段树套替罪羊树。
结果替罪羊树写崩了,打开板子\(QAQ\)。
\(Code:\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define D double
#define N 50005
#define M 850000
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define s(x) a[x].siz
#define cnt(x) a[x].ct
#define val(x) a[x].v
using namespace std;
const int INF=2147483647;
const int FINF=-2147483647;
D alpha=0.8;
struct node
{
int ch[2],siz,v,ct;
}a[M];
int n,m,w[N],rt[N << 2];
int opt,x,l,r,k;
namespace Scapegoat_Tree
{
int tot=0,pool[M+5];
int tp=0,q[N];
int rp,rq;
void Pre()
{
for (int i=M;i>=1;--i)
pool[++tot]=i;
}
void Print(int x)
{
if (ls(x))
Print(ls(x));
printf("%d ",x);
if (rs(x))
Print(rs(x));
}
void print(int x)
{
Print(x);
putchar('\n');
}
int newnode(int x)
{
int o=pool[tot--];
ls(o)=rs(o)=0;
val(o)=x,cnt(o)=s(o)=1;
return o;
}
bool bad(int x)
{
return alpha*(D)s(x)<=(D)max(s(ls(x)),s(rs(x)));
}
void dfs(int x)
{
if (ls(x))
dfs(ls(x));
q[++tp]=x;
if (rs(x))
dfs(rs(x));
}
void update(int x)
{
s(x)=s(ls(x))+s(rs(x))+cnt(x);
}
int build(int l,int r)
{
if (l>r)
return 0;
if (l==r)
{
ls(q[l])=rs(q[l])=0;
s(q[l])=cnt(q[l]);
return q[l];
}
int mid=(l+r) >> 1;
ls(q[mid])=build(l,mid-1);
rs(q[mid])=build(mid+1,r);
update(q[mid]);
return q[mid];
}
void rebuild(int &x)
{
tp=0;
dfs(x);
x=build(1,tp);
}
void ins(int &x,int z)
{
if (!x)
{
x=newnode(z);
return;
}
++s(x);
if (val(x)==z)
{
++cnt(x);
return;
}
int nxt=(z<val(x))?0:1;
ins(a[x].ch[nxt],z);
if (bad(x))
rq=-1; else
if (rq==-1)
rp=x,rq=nxt;
}
void Ins(int &rt,int x)
{
rp=rq=0;
ins(rt,x);
if (rq==-1)
rebuild(rt); else
if (rp)
rebuild(a[rp].ch[rq]);
}
int rmin(int &rt)
{
if (ls(rt))
{
int ret=rmin(ls(rt));
if (bad(rt))
rq=-1; else
if (rq==-1)
rp=rt,rq=0;
update(rt);
return ret;
}
int ret=rt;
rt=rs(rt);
return ret;
}
void del(int &x,int z)
{
if (!x)
return;
--s(x);
if (val(x)==z)
{
--cnt(x);
if (!cnt(x))
{
if (!ls(x))
pool[++tot]=x,x=rs(x); else
if (!rs(x))
pool[++tot]=x,x=ls(x); else
{
int g=rmin(rs(x));
if (rq==-1)
rp=x,rq=1;
val(x)=val(g),cnt(x)=cnt(g);
update(x);
pool[++tot]=g;
if (bad(x))
rq=-1;
}
}
return;
}
int nxt=(z<val(x))?0:1;
del(a[x].ch[nxt],z);
if (bad(x))
rq=-1; else
if (rq==-1)
rp=x,rq=nxt;
}
void Del(int &rt,int x)
{
rp=rq=0;
del(rt,x);
if (rq==-1)
rebuild(rt); else
if (rp)
rebuild(a[rp].ch[rq]);
}
int prk(int x,int k)
{
int ans=0;
while (x)
{
if (val(x)==k)
{
ans+=s(ls(x));
return ans;
}
if (val(x)<k)
ans+=s(ls(x))+cnt(x),x=rs(x); else
x=ls(x);
}
return ans;
}
int rk(int x,int k)
{
return prk(x,k)+1;
}
int kth(int x,int k)
{
for (;;)
{
if (s(ls(x))>=k)
x=ls(x); else
if (s(ls(x))+cnt(x)>=k)
return val(x); else
k-=s(ls(x))+cnt(x),x=rs(x);
}
}
int pre(int x,int k)
{
int ans=FINF;
while (x)
{
if (val(x)<k)
ans=max(ans,val(x)),x=rs(x); else
x=ls(x);
}
return ans;
}
int succ(int x,int k)
{
int ans=INF;
while (x)
{
if (val(x)>k)
ans=min(ans,val(x)),x=ls(x); else
x=rs(x);
}
return ans;
}
};
namespace Segment_Tree
{
void build(int p,int l,int r)
{
for (int i=l;i<=r;++i)
Scapegoat_Tree::Ins(rt[p],w[i]);
if (l==r)
return;
int mid=(l+r) >> 1;
build(p << 1,l,mid);
build(p << 1 | 1,mid+1,r);
}
int rk(int p,int l,int r,int x,int y,int z)
{
if (l==x && r==y)
return Scapegoat_Tree::prk(rt[p],z);
int mid=(l+r) >> 1;
if (y<=mid)
return rk(p << 1,l,mid,x,y,z); else
if (x>mid)
return rk(p << 1 | 1,mid+1,r,x,y,z); else
return rk(p << 1,l,mid,x,mid,z)+rk(p << 1 | 1,mid+1,r,mid+1,y,z);
}
int Rk(int l,int r,int z)
{
return rk(1,1,n,l,r,z)+1;
}
int kth(int x,int y,int k)
{
int l=0,r=100000000,ans=-1;
while (l<=r)
{
int mid=(l+r) >> 1;
if (Rk(x,y,mid)<=k)
ans=mid,l=mid+1; else
r=mid-1;
}
return ans;
}
void modify(int p,int l,int r,int x,int z1,int z2)
{
Scapegoat_Tree::Del(rt[p],z1);
Scapegoat_Tree::Ins(rt[p],z2);
if (l==r)
return;
int mid=(l+r) >> 1;
if (x<=mid)
modify(p << 1,l,mid,x,z1,z2); else
modify(p << 1 | 1,mid+1,r,x,z1,z2);
}
int pre(int p,int l,int r,int x,int y,int z)
{
if (l==x && r==y)
return Scapegoat_Tree::pre(rt[p],z);
int mid=(l+r) >> 1;
if (y<=mid)
return pre(p << 1,l,mid,x,y,z); else
if (x>mid)
return pre(p << 1 | 1,mid+1,r,x,y,z); else
return max(pre(p << 1,l,mid,x,mid,z),pre(p << 1 | 1,mid+1,r,mid+1,y,z));
}
int succ(int p,int l,int r,int x,int y,int z)
{
if (l==x && r==y)
return Scapegoat_Tree::succ(rt[p],z);
int mid=(l+r) >> 1;
if (y<=mid)
return succ(p << 1,l,mid,x,y,z); else
if (x>mid)
return succ(p << 1 | 1,mid+1,r,x,y,z); else
return min(succ(p << 1,l,mid,x,mid,z),succ(p << 1 | 1,mid+1,r,mid+1,y,z));
}
};
int main()
{
Scapegoat_Tree::Pre();
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
scanf("%d",&w[i]);
Segment_Tree::build(1,1,n);
for (int i=1;i<=m;++i)
{
scanf("%d",&opt);
if (opt==1)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_Tree::Rk(l,r,k));
} else
if (opt==2)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_Tree::kth(l,r,k));
} else
if (opt==3)
{
scanf("%d%d",&x,&k);
Segment_Tree::modify(1,1,n,x,w[x],k);
w[x]=k;
} else
if (opt==4)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_Tree::pre(1,1,n,l,r,k));
} else
if (opt==5)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",Segment_Tree::succ(1,1,n,l,r,k));
}
}
return 0;
}