<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      替罪羊樹

      替罪羊樹

      平衡樹的一種。其特點是采用 “摧毀—重建” 的方法維護(hù) BST 的平衡。

      具體而言,當(dāng)我們發(fā)現(xiàn)樹上有一棵子樹不平衡了,就摧毀它,然后重新建一棵平衡的子樹。

      不平衡率

      我們定義不平衡率 \(\alpha\in[0.5,1]\) 為:一棵以 \(u\) 為根的子樹,若其左子樹或右子樹占比大于 \(\alpha\),就認(rèn)為不平衡。

      顯然,當(dāng) \(\alpha=0.5\) 時,BST 是絕對平衡的;當(dāng) \(\alpha=1\) 時,BST 表現(xiàn)為一條鏈。

      替罪羊樹復(fù)雜度的關(guān)鍵就在于 \(\alpha\) 的設(shè)定。根據(jù)某 OIer_Automation 的經(jīng)驗,有修改時,\(\alpha=0.75\) 最優(yōu);無修改時,\(\alpha=0.85\) 最優(yōu)。但是特殊地,在替罪羊樹套某些其他數(shù)據(jù)結(jié)構(gòu)時,應(yīng)當(dāng)盡量減少重構(gòu)的次數(shù),即 \(\alpha\) 應(yīng)盡量取大。

      基本操作

      重構(gòu)

      判斷是否需要重構(gòu),只需判斷最大的一個兒子的大小是否大于當(dāng)前子樹的大小 \(\times\alpha\) 即可。

      bool nbl(int u){
          return max(t[lu].sm,t[ru].sm)>=alpha*t[u].sm;
      }
      

      然后重構(gòu)的時候,先把當(dāng)前子樹拍平,然后按照拍平后的數(shù)組建樹即可。

      void flatten(int u){
          if(!u) return;
          flatten(lu);
          if(t[u].cnt) ord[++cnt]=u;
          flatten(ru);
      }
      void build(int l,int r,int&u){
          if(l>r) return u=0,void();
          int mid=(l+r)>>1;
          u=ord[mid];
          build(l,mid-1,lu),build(mid+1,r,ru);
          update(u);
      }
      void redo(int&u){
          cnt=0;
          flatten(u);
          build(1,cnt,u);
      }
      

      重構(gòu)時的代碼就是

      if(nbl(u)) redo(u);
      

      插入

      替罪羊樹上的一個節(jié)點保存一個當(dāng)前點的數(shù)的數(shù)量。插入時從根往下走,如果沒有新建節(jié)點就新建一個,否則按照大小關(guān)系遞歸即可。

      void ins(int&u,int x){
          if(!u) return t[u=++tot]={0,0,x,1,1,1,1},void();
          if(x==t[u].val) t[u].cnt++;
          else if(x<t[u].val) ins(lu,x);
          else ins(ru,x);
          update(u);
          if(nbl(u)) redo(u);
      }
      

      刪除

      也是同理的。

      void del(int&u,int x){
          if(t[u].val==x) t[u].cnt--;
          else if(x<t[u].val) del(lu,x);
          else del(ru,x);
          update(u);
          if(nbl(u)) redo(u);
      }
      

      其余操作和一般的平衡樹寫法無異。

      模板

      P3369 【模板】普通平衡樹

      constexpr int MAXN=1e5+5;
      constexpr double alpha=0.75;
      int rt;
      struct{
      	#define lu t[u].ls
      	#define ru t[u].rs
      	struct ScapeGoatTree{
      		int ls,rs,val,cnt,s,sd,siz;
      	}t[MAXN];
      	int ord[MAXN],cnt;
      	int tot;
      	void flatten(int u){
      		if(!u) return;
      		flatten(lu);
      		if(t[u].cnt) ord[++cnt]=u;
      		flatten(ru);
      	}
      	void update(int u){
      		t[u].s=t[lu].s+t[ru].s+1;
      		t[u].sd=t[lu].sd+t[ru].sd+(t[u].cnt!=0);
      		t[u].siz=t[lu].siz+t[ru].siz+t[u].cnt;
      	}
      	void build(int l,int r,int&u){
      		if(l>r) return u=0,void();
      		int mid=(l+r)>>1;
      		u=ord[mid];
      		build(l,mid-1,lu),build(mid+1,r,ru);
      		update(u);
      	}
      	void redo(int&u){
      		cnt=0;
      		flatten(u);
      		build(1,cnt,u);
      	}
      	bool nbl(int u){
      		return max(t[lu].s,t[ru].s)>=alpha*t[u].s||alpha*t[u].s>=t[u].sd;
      	}
      	void ins(int&u,int x){
      		if(!u) return t[u=++tot]={0,0,x,1,1,1,1},void();
      		if(x==t[u].val) t[u].cnt++;
      		else if(x<t[u].val) ins(lu,x);
      		else ins(ru,x);
      		update(u);
      		if(nbl(u)) redo(u);
      	}
      	void del(int&u,int x){
      		if(t[u].val==x) t[u].cnt--;
      		else if(x<t[u].val) del(lu,x);
      		else del(ru,x);
      		update(u);
      		if(nbl(u)) redo(u);
      	}
      	int rnk(int u,int x){
      		if(!u) return 0;
      		if(t[u].val==x&&t[u].cnt) return t[lu].siz;
      		else if(t[u].val<x) return t[lu].siz+t[u].cnt+rnk(ru,x);
      		else return rnk(lu,x);
      	}
      	int kth(int u,int k){
      		if(!u) return 0;
      		if(t[lu].siz<k&&k<=t[lu].siz+t[u].cnt) return t[u].val;
      		else if(k<=t[lu].siz) return kth(lu,k);
      		else return kth(ru,k-t[lu].siz-t[u].cnt);
      	}
      	int pre(int u,int x){
      		return kth(u,rnk(u,x));
      	}
      	int nxt(int u,int x){
      		return kth(u,rnk(u,x+1)+1);
      	}
      }T;
      
      int main(){
      	int n=read();
      	while(n--){
      		int opt=read(),x=read();
      		switch(opt){
      			case 1: T.ins(rt,x);break;
      			case 2: T.del(rt,x);break;
      			case 3: write(T.rnk(rt,x)+1);break;
      			case 4: write(T.kth(rt,x));break;
      			case 5: write(T.pre(rt,x));break;
      			default:write(T.nxt(rt,x));break;
      		}
      	}
      	return fw,0;
      }
      

      典型應(yīng)用

      P3920 [WC2014] 紫荊花之戀

      點分樹套替罪羊樹,又稱動態(tài)點分樹。

      點分樹可以很方便地求解帶修處理樹上路徑問題,但是在這道題中這棵樹的形態(tài)還在發(fā)生變化,為了保證樹高為 \(\log n\),我們需要不斷地重構(gòu)點分樹,而這樣做顯然不優(yōu)。

      于是我們采取替罪羊樹的思想:對于一棵子樹,如果它超出了我們設(shè)定的不平衡率,我們就重構(gòu)它。這樣做就可以在一個 \(O(n\log^2n)\) 的時間內(nèi)實現(xiàn)點分樹的動態(tài)插入了。

      然后對應(yīng)到本道題,既然支持了動態(tài)插入,考慮去做 \(\text{dist}(i,j)\le r_i+r_j\) 的計數(shù)。那這個問題就很經(jīng)典了,對于當(dāng)前子樹的根 \(p\),轉(zhuǎn)化為 \(\text{dist}(i,p)+\text{dist}(p,j)\le r_i+r_j\),移項得 \(\text{dist}(i,p)-r_i\le r_j-\text{dist}(p,j)\),按照套路對每個節(jié)點維護(hù) \(\rm SG\)\(\rm CH\) 兩棵平衡樹,分別維護(hù)子樹內(nèi)所有點的 \(\text{dist}(i,p)-r_i\) 的值和 \(\text{dist}(i,\text{fa}(p))-r_i\) 的值,查詢時直接查排名即可。

      posted @ 2025-06-28 09:00  Laoshan_PLUS  閱讀(247)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩人妻精品中文字幕| 在线播放深夜精品三级| 少妇爽到呻吟的视频| 国产欧美丝袜在线二区| 日韩高清免费一码二码三码| 欧美乱妇狂野欧美在线视频| 视频一区视频二区中文字幕| 日本一卡2卡3卡4卡无卡免费| 亚洲一区二区色情苍井空 | 亚洲午夜亚洲精品国产成人| 男受被做哭激烈娇喘gv视频| 亚洲一级特黄大片在线观看 | 成人国产精品中文字幕| 女人张开腿无遮无挡视频| 亚洲国产女性内射第一区| 无码AV中文字幕久久专区| 中文字幕乱妇无码AV在线| 97久久超碰国产精品2021| 在线国产精品中文字幕| 成全影视大全在线观看| 亚洲AV成人一区国产精品| 亚洲这里只有久热精品伊人| 97久久精品亚洲中文字幕无码 | 好看的国产精品自拍视频| 久久这里有精品国产电影网| 国产精品永久免费成人av| 精品一卡2卡三卡4卡乱码精品视频 | 伊人久久大香线蕉综合观| av永久天堂一区| 国产男女爽爽爽免费视频| 年轻女教师hd中字3| 国产精品XXXX国产喷水| 国产精品永久久久久久久久久| 日韩免费视频一一二区| 精品国产中文字幕懂色| 色综合久久综合中文综合网| 天堂一区人妻无码| 国产一区国产二区在线视频| 日产精品99久久久久久| 久久亚洲精品11p| 亚洲色婷婷综合开心网|