今天寫dsu on tree 的時候發現不會寫線段樹合併,於是滾來寫線段樹合併部落格
對於值域相同的兩個權值線段樹x
xx和y
yy(假設把y
yy合併到x
xx上),每個節點有兩種情況:
其中至少有乙個節點沒有權值(!x
∣∣!y
)(!x||!y)
(!x∣∣!
y)直接x =x
+y
x=x+y
x=x+y(x=
=0?y
:x
)(x==0?y:x)
(x==0?
y:x)
兩個點都有權值
v al
[x]+
=val
[y];
val[x]+=val[y];
val[x]
+=va
l[y]
;統計答案
void merge(int &x,int y)//其中乙個不存在(動態開點)
val[x]+=val[y];
getans(x,y);//統計答案
merge(ls[x],ls[y]);
merge(rs[x],rs[y]);//遞迴
}
luogup3521
樹上逆序對
很裸,每次統計答案
注意卡空間
p.s. cdqz的學長std好像空間是o(n)的,都是什麼神仙啊。。
#include#include#includeusing namespace std;
int read()
int n;
const int n=200010;
long long ans,ans1,ans2,tot;
int ls[n*20],rs[n*20];long long val[n*20];
void modify(int l,int r,int &now,int x)
void merge(int &x,int y)
val[x]+=val[y];
ans1+=val[rs[x]]*val[ls[y]];
ans2+=val[ls[x]]*val[rs[y]];
merge(ls[x],ls[y]);
merge(rs[x],rs[y]);
} void dfs(int &now)else modify(1,n,now,num);
}int main()
線段樹合併
做永無鄉的時候,以為是主席樹合併,後來感覺不對勁,唔。x和y是兩顆樹的根。這個演算法是從歸併演算法那引申的。實際運作的時候,考慮到了線段樹的本質 線段樹有效節點就是葉子節點。好像是句廢話。其實不是,這句話啟發我們並不需要合併一整棵樹,我們只需要處理好葉子節點,考慮把y樹合併到x上,那麼把y樹的葉子節...
線段樹合併
某一天馬學長給我看了乙個lca的題目,然而確實是lca 樹上差分,但是僅僅有lca和樹上差分解決不了,然後我就去面向題解程式設計了。可是這個線段樹合併是個什麼東東。然而今天看書,突然看到了這個線段樹合併。就寫一下了。mmh。p4556 vani有約會 雨天的尾巴 題目背景 深繪里一直很討厭雨天。灼熱...
線段樹合併
線段樹合併雖說是比較基礎的內容,且我一直都知道大概的實現方式,但直到最近我才正式去寫過一次,我真的太弱了啊。下面從暴力合併開始,依次介紹幾種線段樹合併的方式。直接暴力摳出線段樹中的元素,然後暴力合併。總合併時間複雜度應為 o n 2logn 應該算是暴力合併的一種優化。即,每次合併時選取較小的一棵線...