#include<cstdio> #define mid(l,r) ((l+r)/2) #define MXN 10000+1 #define nil 0 #define alpha 0.7f int read(){ int x=0; bool w=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') w=0; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+(c-'0'); c=getchar(); } return w?x:-x; } void write(long long x){ int buf[20],p=-1; if(x<0){ putchar('-'); x=-x; } while(x){ buf[++p]=x%10; x/=10; } if(p==-1) putchar('0'); else for(int i=p;i>=0;i--) putchar(buf[i]+'0'); return; } int valw[MXN],valc[MXN],size[MXN],fa[MXN],left[MXN],right[MXN],recycle[MXN],lst[MXN]; int root,ntop,rtop=-1,ltop; int p,x,y; long long wans,cans; void grand_travel(int now,const char* link){ if(now==nil) return; grand_travel(left[now],link); printf("%d",now); printf(link); grand_travel(right[now],link); return; } int newnode(){ int nw; if(rtop!=-1) nw=recycle[rtop--]; else nw=++ntop; valw[nw]=0; valc[nw]=0; size[nw]=1; fa[nw]=nil; left[nw]=nil; right[nw]=nil; return nw; } int newnode(int a,int b){ int nw=newnode(); valw[nw]=a; valc[nw]=b; return nw; } int search(int now,int c){ if(now==nil) return nil; if(valc[now]==c) return now; if(valc[now]>c) return search(left[now],c); if(valc[now]<c) return search(right[now],c); } bool check(int now){ return size[left[now]]>size[now]*alpha||size[right[now]]>size[now]*alpha; } void travel(int now){ if(now==nil) return; travel(left[now]); lst[ltop++]=now; travel(right[now]); return; } int build(int l,int r){ if(l>=r) return nil; int mid=mid(l,r),nw=lst[mid]; left[nw]=build(l,mid); right[nw]=build(mid+1,r); fa[left[nw]]=nw; fa[right[nw]]=nw; size[nw]=size[left[nw]]+size[right[nw]]+1; return nw; } void insert(int &now,int ins){ if(root==nil) root=ins; else if(now==nil) now=ins; else{ size[now]++; if(valc[ins]<valc[now]){ if(left[now]==nil){ left[now]=ins; fa[ins]=now; } else insert(left[now],ins); } else{ if(right[now]==nil){ right[now]=ins; fa[ins]=now; } else insert(right[now],ins); } } return; } void add(int w,int c){ if(search(root,c)!=nil) return; int ins=newnode(w,c); insert(root,ins); int t=0,f,flag,rt; for(int i=ins;fa[i]!=nil;i=fa[i]){ if(check(i)) t=i; } if(t){ ltop=0; f=fa[t]; if(left[f]==t) flag=1; else flag=0; travel(t); rt=build(0,ltop); if(t==root) root=rt; else{ fa[rt]=f; if(flag) left[f]=rt; if(!flag) right[f]=rt; } } return; } void remove(bool flag){ if(root==nil) return; int t=root; if(flag==false){ while(left[t]!=nil){ size[t]--; t=left[t]; } } else{ while(right[t]!=nil){ size[t]--; t=right[t]; } } if(left[t]==nil&&right[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=nil; else right[fa[t]]=nil; if(root==t) root=nil; fa[t]=nil; recycle[++rtop]=t; return; } else if(left[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=right[t]; else right[fa[t]]=right[t]; fa[right[t]]=fa[t]; if(root==t) root=right[t]; fa[t]=nil; recycle[++rtop]=t; return; } else if(right[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=left[t]; else right[fa[t]]=left[t]; fa[left[t]]=fa[t]; if(root==t) root=left[t]; fa[t]=nil; recycle[++rtop]=t; return; } return; } void grand_order(int now){ if(now==nil) return; grand_order(left[now]); wans+=valw[now]; cans+=valc[now]; grand_order(right[now]); return; } int main(){ root=nil; while(1){ p=read(); if(p==-1) break; if(p==1){ x=read(); y=read(); add(x,y); } if(p==3) remove(false); if(p==2) remove(true); } grand_order(root); write(wans); putchar(' '); write(cans); return 0; }
题意请上洛谷。
这是一道平衡树水题。上周末做了Code+的第二次月赛,平衡树那道题没有做出来后,我就感觉要做一些题练习练习。
总之就是一道裸题。以上代码是用我很喜欢的替罪羊树写的,表达一下我的心情,虽然替罪羊树只有平衡树基本的应用。不过替罪羊真的跑得飞快啊。
近来发现Treap好强啊,几乎支持现在所有操作了,还能可持久化……
看来需要学习Treap。
#include<cstdio> #define abs(x) (x>0?x:-x) #define MXN 100000+1 #define nil 0 #define alpha 0.5f int val[MXN],size[MXN],fa[MXN],left[MXN],right[MXN],recycle[MXN]; int root,ntop,rtop=-1; int newnode(){ int nw; if(rtop==-1) nw=++ntop; else nw=recycle[rtop--]; val[nw]=0; size[nw]=1; fa[nw]=nil; left[nw]=nil; right[nw]=nil; return nw; } int newnode(int k){ int nw=newnode(); val[nw]=k; return nw; } bool check(int now){ int a=size[left[now]]-size[right[now]]; return abs(a)>alpha*size[now]; } void rotate(int now){ if(fa[now]==nil) return; int f=fa[now],gf=fa[f],l=left[now],r=right[now]; if(left[gf]==f) left[gf]=now; else right[gf]=now; if(left[f]==now){ right[now]=f; left[f]=r; fa[r]=f; } else{ left[now]=f; right[f]=l; fa[l]=f; } fa[f]=now; fa[now]=gf; size[f]=size[left[f]]+size[right[f]]+1; size[now]=size[left[now]]+size[right[now]]+1; if(fa[now]==nil) root=now; return; } void adjust(int now){ if(check(now)){ if(size[left[now]]>size[right[now]]) rotate(left[now]); else rotate(right[now]); } return; } void insert(int &now,int ins){ if(root==nil) root=ins; else if(now==nil) now=ins; else{ size[now]++; if(val[ins]<val[now]){ if(left[now]==nil){ left[now]=ins; fa[ins]=now; } else insert(left[now],ins); } else{ if(right[now]==nil){ right[now]=ins; fa[ins]=now; } else insert(right[now],ins); } } adjust(now); return; } void remove(int now,int k){ if(now==nil) return; if(k==val[now]){ if(left[now]==nil&&right[now]==nil){ if(left[fa[now]]==now) left[fa[now]]=nil; else right[fa[now]]=nil; if(now==root) root=nil; fa[now]=nil; recycle[++rtop]=now; return; } else if(left[now]==nil){ if(left[fa[now]]==now) left[fa[now]]=right[now]; else right[fa[now]]=right[now]; fa[right[now]]=fa[now]; if(now==root) root=right[now]; fa[now]=nil; recycle[++rtop]=now; return; } else if(right[now]==nil){ if(left[fa[now]]==now) left[fa[now]]=left[now]; else right[fa[now]]=left[now]; fa[left[now]]=fa[now]; if(now==root) root=left[now]; fa[now]=nil; recycle[++rtop]=now; return; } else{ int t=left[now]; while(right[t]!=nil) t=right[t]; val[now]=val[t]; size[now]--; remove(left[now],val[t]); adjust(now); } } else{ size[now]--; if(k<val[now]) remove(left[now],k); else remove(right[now],k); adjust(now); } return; } int search(int now,int k){ if(now==nil) return nil; if(k==val[now]) return now; if(k<val[now]) return search(left[now],k); if(k>val[now]) return search(right[now],k); } void grand_order(int now){ if(now==nil) return; grand_order(left[now]); printf("%d ",val[now]); grand_order(right[now]); return; } int main(){ root=nil; while(1){ int p,x; scanf("%d",&p); if(p==1){ scanf("%d",&x); if(search(root,x)==nil) insert(root,newnode(x)); } if(p==2){ scanf("%d",&x); if(search(root,x)!=nil) remove(root,x); } if(p==3){ grand_order(root); printf(" "); } if(p==0) break; } return 0; }
另一种平衡树A了。
#include<cstdio> #define MXN 100000+1 #define nil 0 int read(){ int x=0; bool w=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') w=0; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+(c-'0'); c=getchar(); } return w?x:-x; } void write(long long x){ int buf[20],p=-1; if(x<0){ putchar('-'); x=-x; } while(x){ buf[++p]=x%10; x/=10; } if(p==-1) putchar('0'); else for(int i=p;i>=0;i--) putchar(buf[i]+'0'); return; } int random(){ static int seed=707; return seed=int(seed*48721LL&2147483647); } int valw[MXN],valc[MXN],rnd[MXN],fa[MXN],left[MXN],right[MXN],recycle[MXN]; int root,ntop,rtop=-1; long long wans,cans; int newnode(){ int nw; if(rtop==-1) nw=++ntop; else nw=recycle[rtop--]; valw[nw]=0; valc[nw]=0; rnd[nw]=random(); fa[nw]=nil; left[nw]=nil; right[nw]=nil; return nw; } int newnode(int w,int c){ int nw=newnode(); valw[nw]=w; valc[nw]=c; return nw; } void rotate(int now){ if(fa[now]==nil) return; int f=fa[now],gf=fa[f],l=left[now],r=right[now]; if(left[gf]==f) left[gf]=now; else right[gf]=now; if(left[f]==now){ right[now]=f; left[f]=r; fa[r]=f; } else{ left[now]=f; right[f]=l; fa[l]=f; } fa[f]=now; fa[now]=gf; if(fa[now]==nil) root=now; return; } void insert(int &now,int ins){ if(root==nil) root=ins; else if(now==nil) now=ins; else{ if(valc[ins]<valc[now]){ if(left[now]==nil){ left[now]=ins; fa[ins]=now; } else insert(left[now],ins); } else{ if(right[now]==nil){ right[now]=ins; fa[ins]=now; } else insert(right[now],ins); } } return; } void remove(bool flag){ if(root==nil) return; int t=root; if(flag==false){ while(left[t]!=nil){ t=left[t]; } } else{ while(right[t]!=nil){ t=right[t]; } } if(left[t]==nil&&right[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=nil; else right[fa[t]]=nil; if(root==t) root=nil; fa[t]=nil; recycle[++rtop]=t; return; } else if(left[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=right[t]; else right[fa[t]]=right[t]; fa[right[t]]=fa[t]; if(root==t) root=right[t]; fa[t]=nil; recycle[++rtop]=t; return; } else if(right[t]==nil){ if(left[fa[t]]==t) left[fa[t]]=left[t]; else right[fa[t]]=left[t]; fa[left[t]]=fa[t]; if(root==t) root=left[t]; fa[t]=nil; recycle[++rtop]=t; return; } return; } int search(int now,int k){ if(now==nil) return nil; if(k==valc[now]) return now; if(k<valc[now]) return search(left[now],k); if(k>valc[now]) return search(right[now],k); } void grand_order(int now){ if(now==nil) return; grand_order(left[now]); wans+=valw[now]; cans+=valc[now]; grand_order(right[now]); return; } int main(){ root=nil; wans=0; cans=0; int p,x,y; while(1){ p=read(); if(p==-1) break; if(p==1){ x=read(); y=read(); if(search(root,y)==nil){ int ins=newnode(x,y); insert(root,ins); while(rnd[ins]<rnd[fa[ins]]&&fa[ins]!=nil) rotate(ins); } } if(p==3) remove(false); if(p==2) remove(true); } grand_order(root); write(wans); putchar(' '); write(cans); return 0; }
带旋TreapAC代码。