關於線段樹

2022-04-10 04:41:17 字數 4080 閱讀 4504

首先肯定推薦學姐部落格!

炒雞優秀的學姐!

主要是貼**,並沒有什麼理論的講解。

例題:洛谷p3372[模板]線段樹1

洛谷p3373[模板]線段樹2

線段樹支援單點查詢、單點修改、區間查詢、區間修改等操作。

基本思想是二分

將線段樹節點用乙個結構體打包起來

建樹:

build(1, 1

, n);

void build (int k, int ll, int

rr)

int mid = (tr[k].l + tr[k].r ) >> 1

; build (lson, ll, mid);

build (rson, mid + 1

, rr);

tr[k].v = tr[lson].v +tr[rson].v;

}

單點查詢:

void ask_point(int

k) mid = (tr[k].l + tr[k].r) >> 1

;

if(x <= mid) ask_point(k << 1

);

else ask_point(k << 1 | 1

);}

單點修改:

void change_point(int

k) mid = (tr[k].l + tr[k].r) >> 1

;

if(x <= mid) change_point(k << 1

);

else change_point(k << 1 | 1

); tr[k].w = tr[k << 1].w + tr[k << 1 | 1

].w;

}

區間查詢:

void ask_query (int

k)

if(tr[k].f) down (k);

int m = (tr[k].l + tr[k].r) >> 1

;

if (z <=m) ask (lson);

if (y >m) ask (rson);

tr[k].v = tr[lson].v +tr[rson].v;

}

區間修改:

void change_query (int

k)

if(tr[k].f) down (k);

int m = (tr[k].l + tr[k].r) >> 1

;

if (z <=m) c_v (lson);

if (y >m) c_v (rson);

tr[k].v = tr[lson].v +tr[rson].v;

}

lazy標記:

void down (int

k)

感性理解

例一**:

#include #include 

//#define int long long

//#define long long int

#define lson k << 1

#define rson k << 1 | 1

using

namespace

std;

intn, m, z, y, w;

long

long

ans;

struct

node tr[

400001

];void build (int k, int ll, int

rr)

int mid = (tr[k].l + tr[k].r ) >> 1

; build (lson, ll, mid);

build (rson, mid + 1

, rr);

tr[k].v = tr[lson].v +tr[rson].v;

}void down (int

k) void c_v (int

k)

if(tr[k].f) down (k);

int m = (tr[k].l + tr[k].r) >> 1

;

if (z <=m) c_v (lson);

if (y >m) c_v (rson);

tr[k].v = tr[lson].v +tr[rson].v;

}void ask (int

k)

if(tr[k].f) down (k);

int m = (tr[k].l + tr[k].r) >> 1

;

if (z <=m) ask (lson);

if (y >m) ask (rson);

tr[k].v = tr[lson].v +tr[rson].v;

}int

main ()

else

if (x == 2

) }

return0;

}

例二**:

#include #include 

using

namespace

std;

struct

node tr[

400000

];long

long

a, b, ans, y, n, m, p;

intread ()

while (isdigit (ch))

return s *w;

}void build (int k, int ll, int

rr)

int m = (ll + rr) >> 1

; build (k

<< 1

, ll, m);

build (k

<< 1 | 1, m + 1

, rr);

tr[k].w = (tr[k << 1].w + tr[k << 1 | 1].w) %p;

return;}

void down (int

k) void mul_interval (int

k) down (k);

int m = (tr[k].l + tr[k].r) >> 1

;

if (a <= m) mul_interval (k << 1

);

if (b > m) mul_interval (k << 1 | 1

); tr[k].w = (tr[k << 1].w + tr[k << 1 | 1].w) %p;

return;}

void add_interval (int

k) down (k);

int m = (tr[k].r + tr[k].l) >> 1

;

if (a <= m) add_interval (k << 1

);

if (b > m) add_interval (k << 1 | 1

); tr[k].w = (tr[k << 1].w + tr[k << 1 | 1].w) %p;

return;}

void ask_interval (int

k) down (k);

int m = (tr[k].r + tr[k].l) >> 1

;

if (a <= m) ask_interval (k << 1

);

if (b > m) ask_interval (k << 1 | 1);}

intmain ()

else

if (nu == 2

)

else

if (nu == 3

) }

return0;

}

謝謝收看, 祝身體健康!

關於線段樹基礎

必須 二分法,樹的基礎 拓展 補碼,反碼,移碼,lowbit 了解什麼是線段樹及用途 線段樹,類模板題 just a hook include include include include include using namespace std const int t 100009 struct ...

題解 線段樹 關於時間

這是本蒟蒻的原創題 確實很簡單 本蒟蒻loj賬號diogenes 本題的難點在於每個操作會重複多次。核心思想是把第t秒的操作提前到第一秒,再減去多餘的部分。有一種構造方法 ad d i.j add i.j 表示區間 i j i,j 需要加的值。de l i.j del i.j 表示區間 i j i,...

關於吉利線段樹

這玩意兒又稱 segment tree beats 由吉老師 picks 美國隊長三位知名毒瘤發明。我的精神受到了汙染.線段樹什麼的太難了,不是很會啊.線段樹最強的地方在於,如果標記支援合併,那麼我們就能夠快速進行區間修改了。維護這樣乙個標記 a,b 表示 x to max x a b 顯然標記可合...