線段樹(區間求和,區間加,單點更新等)

2021-10-01 16:18:58 字數 3205 閱讀 3931

線段樹是一種二叉搜尋樹。它將一段區間劃分為若干個單位區間,每乙個節點都儲存著乙個區間。

線段樹可做 區間求和,區間最值,區間更新,單點更新等操作

以區間和為例來做介紹:

建樹

const int maxn=1000000+5;

struct treetree[maxn*2];

//把子節點的資訊彙總到了父節點上,根據題目要求可做修改,比如可以更改為區間最值

void pushup(int cur)

void build(int l,int r,int step)

//如果不是葉節點,就一直左右遞迴找,直到找到為止

build(l,mid,step*2);

build(mid+1,r,step*2+1);

//將子節點的值彙總給父親節點,用於求和

pushup(step);

}

單點更新 hdu-1166
//單點值的更改,找指定的葉節點

//將tar節點的值增加val

void update(int tar, int val, int step)

int mid = (l + r) / 2;

if (tar <= mid)

update(tar, val, 2 * step);

else

update(tar, val, 2 * step + 1);

pushup(step);

}

區間更新
/************************************** poj-3468 ***************************************/

//區間加

#include#include#includeusing namespace std;

#define maxn 100000 + 5

long long a[maxn];

struct treetree[maxn << 2];

//把子節點匯集到父節點

void push_up(int step)

//區間加後向下更新

void push_down(int step)

}void buildtree(int step, int l, int r)

return;

}long long query(int step, int l, int r)

void u_update(int step, int l, int r, int val)

else

push_up(step);

} return;

}int main()

else

} return 0;

}/******************************** hdu 1698 *************************************/

//將[l,r]區間內的值更換為val,需要用到標記

#includeconst int maxn = 10000000 + 5;

struct tree tree[maxn];

void build(int l, int r, int step)

void update(int l, int r, int val, int step)

if (tree[step].val != -1)

int mid = (tree[step].l + tree[step].r) / 2;

if (r <= mid)

update(l, r, val, step * 2);

else if (l > mid)

update(l, r, val, step * 2 + 1);

else

}int query(int step)

int main()

printf("case %d: the total value of the hook is %d.\n", i, query(1));

}}

區間查詢
//查詢區間[ql,qr]裡面元素的總和

int query(int ql,int qr,int cur)

**用處:**一般線段樹開局直接4*n的空間,然而當n很大時,4倍空間會消耗很多,這時考慮用動態開點線段樹,用多少開多少,跟c++的new差不多

**預備:**乙個根節點root,存值陣列c[n],左右兒子 lc[n],rc[n]

演算法流程:

1.一開始只有乙個根節點

2.update操作:類似串演算法,每次傳入節點root,區間範圍[l,r]和更新點x,判斷x在區間的哪邊,在哪邊就就往哪邊走,如果遇到乙個無標記的節點但又需要往這個節點走

就以訪問次序給這個節點標號,像正常線段樹更新即可。

3.query操作:和一般線段樹不同的是,當我們遇到乙個沒有訪問過的節點,直接返回,其他與線段樹查詢一致。

假設我們要對 1 3 5 7 8 9這段序列操作,區間範圍[1,9] 開的線段樹如下可以少點2,4,6這3個兒子節點

如果這段區間沒有5,我們甚至可以不用開7號和8號節點

//以求逆序對為例

#include #include #include #includeusing namespace std;

const int n = 5e6 + 10;

int root, n, c[n], lc[n], rc[n], cnt;

void update(int &p, int l, int r, int x, int val)

int mid = (l + r) >> 1;

if (x <= mid) update(lc[p], l, mid, x, val);

else update(rc[p], mid + 1, r, x, val);

c[p] = c[lc[p]] + c[rc[p]];

}int query(int p, int l, int r, int x, int y)

int main()

cout << ans << endl;

} return 0;

}

線段樹(區間求和,區間加,單點更新等)

線段樹是一種二叉搜尋樹。它將一段區間劃分為若干個單位區間,每乙個節點都儲存著乙個區間。線段樹可做 區間求和,區間最值,區間更新,單點更新等操作 以區間和為例來做介紹 建樹const int maxn 1000000 5 struct treetree maxn 2 把子節點的資訊彙總到了父節點上,根...

線段樹 的單點更新和區間求和

include int sum 100 void build int lift,int right,int rt void updata int point,int add,int lift,int right,int rt int query int l,int r,int l,int r,int...

線段樹(區間更新求和)

poj 3468 include using namespace std define max 100100 struct node 求區間長度 int get dis node tree max 3 long long d max 建樹 long long build int left,int r...