Luogu3380 【模板】二逼平衡樹(樹套樹)
阿新 • • 發佈:2020-11-12
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; }