日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线段树合并、分裂

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线段树合并、分裂 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本概念:

如果需要維護許多個大小為 \(10^5\) 級別的多重集,可以看做給每一個多重集建立一棵線段樹。線段樹的合并、分裂就是多重集的累加、分開。

這里使用動態開點的方式存儲線段樹樹。

如果一個節點為空,那么它的編號為 \(0\)

變量釋義:

  • \(cnt\) 個多重集

  • 建立了 \(tot\) 個節點

  • 若一個多重集的編號為 \(x\) ,它的根節點編號為 \(root[x]\)

注意:空間是個謎!能開多大是多大

線段樹合并

把以 \(y\) 為根的線段樹合并到以 \(x\) 為根的線段樹:

int merge(int x,int y,int nl,int nr) // i:y->x {if(!x || !y) return x+y;int mid=(nl+nr)>>1;//tree[x].sum+=tree[y].sum; 根據題目改動tree[x].ls=merge(tree[x].ls,tree[y].ls,nl,mid);tree[x].rs=merge(tree[x].rs,tree[y].rs,mid+1,nr);//pushup(x);del(y);return x; }

復雜度 \(=\) 節點數 ( 一般均攤下來可以達到一次操作 \(O(\log n)\) 的級別 )

線段樹分裂

把以 \(x\) 為根的線段樹中 \(\ge k\) 的數轉移到一棵 空的 線段樹 \(y\)

void split(int &x,int &y,int nl,int nr,int k) // i>=k i:x->y {if(!x) x=++tot;if(!y) y=++tot;if(nl==nr) { swap(x,y); return; }int mid=(nl+nr)>>1;if(mid>=k){swap(tree[x].rs,tree[y].rs);split(tree[x].ls,tree[y].ls,nl,mid,k);}else split(tree[x].rs,tree[y].rs,mid+1,nr,k);pushup(x),pushup(y); }

例題:

P5494 【模板】線段樹分裂 \(\rightarrow\) 模板代碼

總結

以上是生活随笔為你收集整理的线段树合并、分裂的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。