1. 程式人生 > >[學習筆記]替罪羊樹

[學習筆記]替罪羊樹

kth pac 不用 data- enable lin date com names

替罪羊樹——簡單粗暴的數據結構 - a_forever_dream的..._CSDN博客

一種簡單粗暴的數據結構(我自認為暴力“不優雅”。。。)

和其他“優雅”的splay,fhq-treap不同

替罪羊既不旋轉,也不分裂合並

我看誰不順眼,直接讓其暴力重構!

思路就是這樣。

特點是:

1.如果一個點的左子樹或者右子樹的節點個數>x的節點個數*alpha(0.5~1.0之間的一個值),那麽暴力重構整個子樹

2.懶惰刪除,因為SGT不夠靈活。對刪除的點打上標記,並且在祖先節點更新信息。但是不刪掉節點本身(名存實亡)。

3.如果一個點子樹的已經刪除部分占30%左右,暴力重構子樹

所以,一個點的信息是:

sz:子樹節點個數

cnt:子樹實際存在的節點個數

val:自己的權值

ch[2]:兩個兒子

die:是否被刪除

先說暴力重構:

分三步:

1.dfs(x),把x子樹所有沒有刪除的點加入一個數組裏

2.build(l,r),分治建樹

3.pushup(fa[x])把x的father的信息更新一下(node中可以不記錄father,臨時記錄即可)

操作:

(最大的坑莫過於未考慮到名存實亡的點)

insert:類比splay,while循環,找到位置之後加入節點(可以同一個值分成不同的點,x和左右子樹的關系變成不嚴格的即可)

    最後從上而下嘗試rebuild

dele:找到後die=1,

    註意:必須找到一個沒有被刪除的。所以,不用權值找,而用第k大(坑了2h)

    (權值的話,如果x被刪除了你不知道往哪裏走)

    最後從上而下嘗試rebuild

rank,kth,pre,bac都差不多,kth的返回,註意當前點必須是未刪除點

復雜度:alpha調好,可以保證O(nlogn)(alpha一般是0.75)

代碼:

P3369 【模板】普通平衡樹

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define il inline
#define reg register int
#define numb (ch^‘0‘)
using
namespace std; typedef long long ll; il void rd(int &x){ char ch;bool fl=false; while(!isdigit(ch=getchar()))(ch==-)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=100000+5; const double al=0.75; struct node{ int ch[2],val; int sz,cnt; bool die; void init(int v){ sz=1;cnt=1;val=v;ch[0]=0;ch[1]=0; } }t[N]; void pushup(int x){ if(!x) return; t[x].sz=t[t[x].ch[0]].sz+t[t[x].ch[1]].sz+1; t[x].cnt=t[t[x].ch[0]].cnt+t[t[x].ch[1]].cnt+(!t[x].die); } int rt; int tot=0; int q[N],num; int isbad(int x){ return (t[t[x].ch[0]].sz>t[x].sz*al||t[t[x].ch[1]].sz>t[x].sz*al||t[x].cnt<t[x].sz*al); } void dfs(int x){ if(!x) return ; dfs(t[x].ch[0]); if(!t[x].die) { q[++num]=x; // cout<<t[x].val<<" "; } dfs(t[x].ch[1]); } int build(int l,int r){//warning!! no consider fa if(l>r) return 0; int mid=(l+r)>>1; int x=q[mid]; // t[x].fa=0; t[x].ch[0]=build(l,mid-1); t[x].ch[1]=build(mid+1,r); // t[t[x].ch[0]].fa=x; // t[t[x].ch[1]].fa=x; pushup(x); return x; } void rebuild(int &x){ //cout<<" rerererreuildbuilbublilbiulib "<<x<<endl; //cout<<" xxx "<<x<<endl; num=0; //x=2;return; //int y=t[x].fa; // int d=t[y].ch[1]==x; dfs(x); //cout<<" num "<<num<<endl;; // for(reg i=1;i<=num;++i){ // cout<<t[q[i]].val<<" "; // }cout<<endl; x=build(1,num); // cout<<" xx "<<x<<endl; pushup(x); } int sta[N],top; void ins(int v){ if(!rt){ rt=++tot; t[rt].init(v); return; } int x=rt; top=0; while(1){ int d=t[x].val<=v; ++t[x].sz; ++t[x].cnt; sta[++top]=x; if(!t[x].ch[d]){ t[x].ch[d]=++tot; t[tot].init(v); break; } x=t[x].ch[d]; } int las=0; for(reg i=1;i<=top;++i){ if(isbad(sta[i])){ if(las==0) { // cout<<" rrt "<<endl, rebuild(rt); // cout<<rt<<" val "<<t[rt].val<<endl; } else rebuild(t[las].ch[t[las].ch[1]==sta[i]]),pushup(las); return; } las=sta[i]; } } void del(int k){ int x=rt; top=0; while(1){ int d=t[t[x].ch[0]].cnt+(!t[x].die); sta[++top]=x; --t[x].cnt; if(!t[x].die&&d==k) { t[x].die=1; break; } if(t[t[x].ch[0]].cnt>=k) x=t[x].ch[0]; else{ k-=d;x=t[x].ch[1]; } } int las=0; for(reg i=1;i<=top;++i){ if(isbad(sta[i])){ if(las==0) rebuild(rt); else //cout<<" las "<<las<<endl, rebuild(t[las].ch[t[las].ch[1]==sta[i]]),pushup(las); return; } las=sta[i]; } } int kth(int k){ int x=rt; while(1){ // cout<<" xx "<<x<<" "<<t[x].val<<" "<<t[x].sz<<" "<<t[x].cnt<<endl; int d=t[t[x].ch[0]].cnt+(!t[x].die); if(!t[x].die&&d==k) return t[x].val; if(t[t[x].ch[0]].cnt>=k) x=t[x].ch[0]; else{ k-=d;x=t[x].ch[1]; } } return -23333333; } int rk(int v){ int x=rt; int ret=1; while(x){ int d=t[x].val<v; if(d) ret+=t[t[x].ch[0]].cnt+(!t[x].die),x=t[x].ch[1]; else x=t[x].ch[0]; } //cout<<" ret "<<ret<<endl; return ret; } int n; int main(){ rd(n); int op,x; for(reg i=1;i<=n;++i){ rd(op);rd(x); if(op==1) ins(x); else if(op==2) del(rk(x)); else if(op==3) printf("%d\n",rk(x)); else if(op==4) printf("%d\n",kth(x)); else if(op==5) printf("%d\n",kth(rk(x)-1)); else printf("%d\n",kth(rk(x+1))); // cout<<" rt "<<rt<<" "<<t[rt].val<<" :: "<<t[rt].sz<<" "<<t[rt].cnt<<endl; } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/2/5 19:28:58 */

[學習筆記]替罪羊樹