标签:line while merge turn || == pre bsp span
完全能代替splay的完美算法!
核心操作:merge
int merge(int x,int y) { if(!x||!y) return x|y; if(rnd[x]<rnd[y]) { down(x); rs[x]=merge(rs[x],y); up(x); return x; } else { down(y); ls[y]=merge(x,ls[y]); up(y); return y; } }
裂开:split
void split_s(int p,int k,int &x,int &y) { //按子树大小分 if(!p) { x=y=0; return; } down(p); /**/ if(siz[ls[p]]>=k) { /**/ y=p; split_s(ls[p],k,x,ls[p]); /**/ } else { /**/ x=p; split_s(rs[p],k-(siz[ls[p]]+1),rs[p],y); /**/ } up(p); }
void split_k(int p,int k,int &x,int &y) { //按权值分 if(!p) { x=y=0; return; } if(k>=c[p]) { x=p; split_k(rs[p],k,rs[p],y); } else { y=p; split_k(ls[p],k,x,ls[p]); } up(p); }
新开节点:New
inline int New(int x) { c[++tot]=x; siz[tot]=1; rnd[tot]=rand(); return x; }
找子树第K大:kth
inline int kth(int p,int k) { //子树第k大 while(1) { if(k<=siz[ls[p]]) p=ls[p]; else { if(k==siz[ls[p]]+1) return p; k-=(siz[ls[p]]+1); p=rs[p]; } } }
把序列分成1-(l-1),l-r,(r+1)-n
split(rt,l-1,x,y); split(y,r-l+1,y,z); //注意是r-l+1
up时注意不要算空节点(比如取max时可能存在负数)
标签:line while merge turn || == pre bsp span
原文地址:https://www.cnblogs.com/wsfwsf/p/13226962.html