一本通學習筆記 樹鏈剖分

2022-06-07 07:06:11 字數 2931 閱讀 4441

loj上只掛了兩個無重的題,本來心想水一下,結果被sdoi2011染色那題卡了一發。儘管這題之前做過,但實現很不優美。今天wa的第一發一開始測樣例就掛了,強行除錯半天交上去一分沒有。後來仔細想了想怎樣寫比較清楚(儘管看起來好像有點冗餘),寫好以後一路順風一發就過。從這裡也有點感悟吧。

#include #define int long long

using namespace std;

const int n = 1000005;

int n, m, q, t1, t2, t3, t4;

namespace seg

void build(int p, int l, int r, int *src) else

}void modify(int p, int l, int r, int pos, int val) else else

pushup(p);

}}int querya(int p, int l, int r, int ql, int qr)

if (l >= ql && r <= qr) else

}int queryb(int p, int l, int r, int ql, int qr)

if (l >= ql && r <= qr) else

}} // namespace seg

namespace tree

}void dfs2(int p)

for (int i = 0; i < g[p].size(); i++)

}void presolve()

void modify(int p, int val)

int querya(int p, int q)

if (dep[p] < dep[q])

swap(p, q);

return max(ret, seg::querya(1, 1, n, dfn[q], dfn[p]));

}int queryb(int p, int q)

if (dep[p] < dep[q])

swap(p, q);

return ret + seg::queryb(1, 1, n, dfn[q], dfn[p]);

}} // namespace tree

int src[n], tmp[n];

signed main()

tree::presolve();

for (int i = 1; i <= n; i++)

for (int i = 1; i <= n; i++)

seg::build(1, 1, n, src);

cin >> q;

for (int i = 1; i <= q; i++)

if (op[1] == 'm')

if (op[1] == 's')

}}

這題的思路很常規,無非就是線段樹每個節點除了維護答案多維護左邊和右邊的顏色,然後由於這個答案可以被快速合併,暴力一下就可以了。

線段樹的部分畢竟都是按順序的所以很容易。但樹鏈剖分查詢的時候由於順序翻轉之類的問題,開個結構體以後事情變得清楚了很多。

類似的問題還有很多,比如維護最大欄位和,加等差數列求和等等,把結點物件稍微封裝一下其實就會很容易。當然自己碼力太弱才是真原因啊~~

#include using namespace std;

const int n = 1000005;

int n, m, t1, t2, t3, t4, src[n], tmp[n];

namespace seg

void pushdown(int p)

void build(int p, int l, int r, int *src) else

}void modify(int p, int l, int r, int ql, int qr, int val) else

}int query(int p, int l, int r, int ql, int qr, int &rl, int &rr) else

}int query(int ql, int qr, int &rl, int &rr)

}void dfs2(int p)

for (int i = 0; i < g[p].size(); i++)

}void presolve()

struct result

};result merge(result a, result b)

int query(int p, int q)

if (dep[p] < dep[q])

swap(p, q), inv ^= 1;

result tmp;

tmp.get(dfn[q], dfn[p]);

ret[inv] = merge(tmp, ret[inv]);

swap(ret[0].cl, ret[0].cr);

result ans = merge(ret[0], ret[1]);

return ans.ans;

}void modify(int p, int q, int v)

if (dep[p] < dep[q])

swap(p, q);

seg::modify(1, 1, n, dfn[q], dfn[p], v);

}} // namespace tree

int main()

tree::presolve();

for (int i = 1; i <= n; i++) src[tree::dfn[i]] = tmp[i];

seg::build(1, 1, n, src);

for (int i = 1; i <= m; i++) else

}return 0;

}

一本通學習筆記 最短路徑

最短路徑常用演算法有dijkstra和spfa。spfa支援負數權重,但容易被毒瘤資料卡。想讓spfa跑快點可以加入乙個小優化 用deque代替queue,然後在push的時候分類,如果比當前front的dis要小就push front,否則push back。最短路計數和次短路問題仿照普通dp處理...

樹鏈剖分學習筆記

寫 又犯了很sb的錯誤,線段樹寫錯了。好像每次都會把r l 1寫成l r 1,然後就只有20分。寫的比較醜,壓了壓之後190行。基本上是我打過的最長的乙個模板了 然後簡單介紹一下樹剖吧。樹鏈剖分,就是把樹剖分成鏈,然後用資料結構來維護這些鏈,使得詢問 修改的複雜度達到o logn o l ogn 不...

樹鏈剖分學習筆記

樹鏈剖分 mod estc oder modestcoder modest code r如果你是重兒子,你就在重路徑上。如果你是輕兒子,暴力沿著祖先向上爬最多log nlogn logn 次就可以遇到重路徑。或者到根 而樹上操作基本就是找祖先 也許有人喜歡我的碼風 include include d...