can you answer these queries?gss系列是spoj出品的一套資料結構好毒瘤題,主要以線段樹、平衡樹和樹鏈剖分為背景,進行了一些操作的魔改,使得難度遠超模板題,但對於思維有極大的提公升。
所以我會選擇一些在我能力範圍內的題挖坑選講,構成乙個gss系列。至於剩下那些,等我成為巨佬弄懂了再說吧。
原題傳送門(洛谷)
gss1:區間最大子段和。(題解:csdn, 個人部落格)
樹鏈剖分
給定一棵樹,動態修改兩點路徑上的點權,查詢兩點路徑上的最大子段和。
最大子段和又雙叒叕公升級啦!!
這次變成了樹上修改和查詢。
其實樹鏈剖分的精髓部分就在於線段樹以及最後跳鏈的部分,那麼我們就從這兩個地方入手。線段樹上的最大子段和並沒有什麼特殊的地方,直接用gss1的做法即可。主要難點在於跳鏈查詢。
我們會發現,跳鏈的時候區間不一定是連續的,那麼最後對答案的合併就是乙個較大的問題。再進一步思考,會發現由於查詢的是最大子段和,所以合併的時候要是把左右區間搞反,就會直接掛掉。所以我們考慮在跳鏈的時候分類討論。
我們設兩個變數分別記錄上一次跳x
xx和上一次跳y
yy的結果,都作為當前跳鏈的右區間,然後查詢相應的重鏈上的結果,作為左區間,最後合併到x
xx和y
yy在同一條重鏈上為止,最後分類討論跳x
xx還是跳y
yy,在合併的時候為了合併的正確性,我們把所有跳x
xx的結果合併後的總區間翻轉(實際上只交換了lsls
ls和r srs
rs),再與y
yy的答案合併。
由於本題合併操作較多,建議寫乙個merge函式。
還有,應該不需要**了吧。(作者畫圖畫到自閉)
#include
#define max 100005
#define inf (ll)1e16
#define ll long long
#define int ll
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define mid ((l+r)>>1)
using
namespace std;
int n, q, cnt, tot;
int head[max]
, next[max*2]
, vet[max*2]
;int sz[max]
, top[max]
, f[max]
, son[max]
, d[max]
, id[max]
, rk[max]
;ll val[max]
;void
add(
int x,
int y)
void
dfs1
(int x,
int fa)
}void
dfs2
(int x,
int t)
}/****segment tree***/
struct node
} s[max*4]
;ll tag[max*4]
;inline node merge
(node a, node b)
inline
void
push_up
(int x)
inline
void
mark
(int p,
int l,
int r, ll k)
inline
void
push_down
(int p,
int l,
int r)
void
build
(int p,
int l,
int r)
build(lc
(p), l, mid)
;build(rc
(p), mid+
1, r)
;push_up
(p);
}void
update
(int p,
int l,
int r,
int ul,
int ur, ll k)
push_down
(p, l, r);if
(mid >= ul)
update(lc
(p), l, mid, ul, ur, k);if
(mid < ur)
update(rc
(p), mid+
1, r, ul, ur, k)
;push_up
(p);
}node query
(int p,
int l,
int r,
int ul,
int ur)
push_down
(p, l, r);if
(mid < ul)
else
if(mid >= ur)
else
}/******end******/
void
modify
(int x,
int y, ll k)
update(1
,1,n, id[top[x]
], id[x]
, k)
; x = f[top[x]];
}if(id[x]
> id[y]
)swap
(x, y)
;update(1
,1,n, id[x]
, id[y]
, k);}
ll get_mx
(int x,
int y)
else}if
(id[x]
< id[y]
)else
swap
(qx.ls, qx.rs)
; res =
merge
(qx, qy)
;return res.mx;
}signed
main()
int x, y;
for(
int i =
1; i < n; i++
)dfs1(1
,0);
dfs2(1
,1);
build(1
,1,n);
cin >> q;
int t;
ll k;
for(
int i =
1; i <= q; i++
)else
}return0;
}
LCA的樹鏈剖分實現
這篇本來是要在 樹鏈剖分小節 中寫的,但是我感覺這只是樹鏈剖分的乙個衍生物,所以另開了一篇,如果對樹鏈剖分部分還不是太了解,請看上面的鏈結。計算樹中兩個節點的最近公共祖先,我們一般有爬山法,tarjan離線演算法,或者是將lca轉換成rmq來解,這裡講一講一種新的求lca的演算法,它是基於樹鏈剖分的...
狐假虎威的樹鏈剖分
運算元據結構 線段樹 結束語 最近在做運輸計畫這道題時,發現要用數鏈剖分,於是就打算學學這個玩意兒。其實之前一直以為這個東西是個很複雜的東西,可能 看起來都很長。但是,學了之後,我才發現,這個東西很好懂,而且 之所以很長,也有乙個原因就是它需要使用乙個強大的資料結構 線段樹。線段樹的 其實並不算少,...
樹鏈剖分的學習理解
前言 本文僅為本人學習樹鏈剖分的理解和總結,有誤之處請大佬指點迷津。也有與其他部落格不同或矛盾之處。樹鏈剖分 顧名思義,將樹結構,剖分成鏈狀結構,然後將一條條的鏈拼接成線性結構,然後就可以通過線段樹 樹狀陣列等維護了。說白了就是在樹上,有些值不好維護,通過樹鏈剖分轉化成乙個序列,而序列就好維護了。樹...