學習筆記——線段樹合併
阿新 • • 發佈:2022-04-13
資料結構
動態開點
有的時候線段樹節點很多,並不需要一次全部建完整棵樹,此時需要動態開點。
由於點是動態開的,所以每個點的位元組點不是固定的,需要特意存一下。
權值線段樹
權值線段數維護的不再是區間了,而是一堆桶。
舉個例子,我們現在有一個長度為 10 的陣列 1,5,2,3,4,1,3,4,4,4
。
\(1\) 出現了 \(2\) 次,\(2\) 出現了 \(1\) 次,\(3\) 出現了 \(2\) 次,\(4\) 出現了 \(4\) 次,\(5\) 出現了 \(1\) 次。
那麼這個線段樹長這樣:
線段數合併
程式碼
namespace XDS{ ll tot=0; struct XDS_{ll lson,rson,val;}tr[N*40]; #define ls(p) tr[p].lson #define rs(p) tr[p].rson #define va(p) tr[p].val #define bdmd ll mid=(l+r)>>1 inline ll NewP(ll val){ ++tot; ls(tot)=0; rs(tot)=0; va(tot)=val; return tot; } inline void UpdateP(ll &p,ll l,ll r,ll x,ll val){ if(!p)p=NewP(0); if(r<x||l>x)return; if(l==r)va(p)+=val; else{ bdmd; UpdateP(ls(p),l,mid,x,val); UpdateP(rs(p),mid+1,r,x,val); va(p)=va(ls(p))+va(rs(p)); } return; } inline ll Ask(ll p,ll l,ll r,ll le,ll ri){ if(!p)return 0; if(r<le||l>ri)return 0; if(le<=l&&r<=ri)return va(p); else{ bdmd; ll ans1=Ask(ls(p),l,mid,le,ri); ll ans2=Ask(rs(p),mid+1,r,le,ri); return ans1+ans2; } } inline ll Merge(ll p1,ll p2,ll l,ll r){ if(!p1)return p2; if(!p2)return p1; if(l==r)va(p1)+=va(p2); else{ bdmd; ls(p1)=Merge(ls(p1),ls(p2),l,mid); rs(p1)=Merge(rs(p1),rs(p2),mid+1,r); va(p1)=va(ls(p1))+va(rs(p1)); } return p1; } #undef ls #undef rs #undef va #undef md }