線段樹的總結

2021-06-23 06:47:13 字數 1867 閱讀 5749

線段樹

線段樹是擅長處理區間的一棵完美二叉樹(所有的葉子的深度相同,並且每個節點要麼是葉子要麼是有兩個兒子的樹),樹上的每個節點都維護乙個區間,根維護的是整個區間,每個節點維護的是父親的區間二等分後的其中乙個子區間。

線段樹的修改分為區間修改和點修改,查詢分為點查詢和區間查詢。

初始化函式:

void init(int n_)

}

區間修改:

區間修改需要給線段樹增加新的域(就是維護多個值),中間有些會用到懶標記和懶標記下發函式(例如區間賦值),有些不會用到如區間加值,

下面分別給出這兩個模板。

區間賦值:(push_down為下放函式)

void push_down(int k,int co)

void update(int a,int b,int co,int k,int l,int r)

}

區間加值:

void add(int a,int b,int x,int k,int l,int r)

}

對應區間加值的區間查詢:

long long sum(int a,int b,int k,int l,int r)

}

線段樹的查詢方式根據題意可能有很多種,但是更新的方式相對單一,下面給出例題。

poj 2828
大致題意:給你一列數和每個數插入的位置,並且後插入的數會佔據當前的位置,並且把當前位置上的數擠到下乙個位置上去,問操作完所有插入操作後所得到的序列。
思路:因為每個位置必然會被最後插入此位置的數佔據,所以我們可以從後往前來構造這個序列,從最後乙個操作開始,對於每乙個數,如果其插入的位置當前的狀態為空則將此數插入到這個位置上,否則就向右尋找最近的空位置,將其插入,注意到posi的範圍是0~i-1所以這樣構造的序列最後一定是符合題意的。但是分析到這裡還是不夠的,再進一步分析我們會發現,向右尋找最近的空位置其本質就是把所有沒空的位置挖掉,然後產生乙個新的位置序列,在這個新的序列上再按插入位置的編號來找尋所在的位置,插入後再將插入位置挖去,產生乙個新的位置序列。再進一步想,
對於某個插入位置x,其實際的位置就是第x個空位置。 到了這裡我們就可以想到用線段樹來做了,開始的時候我將每個位置都設為1,用線段樹來維護乙個前n項和,對於某個插入x,我們只要找的前n項和為x的位置k即可,在插入操作完成之後再將位置k的值更新成0即可。~~~
code:
#include #include #include #include#include #define inf 1000000000

#define eps 1e-9

using namespace std;

typedef long long ll;

const int max_e=200;

const int max_v=100;

const int max_m=110;

const int max_n=800000;

int n,dat[2*max_n-1];

void init(int n_)

}int query(int m,int k,int l,int r)

int a[max_n];

struct node

p[max_n];

int main()

for(int i=0;i未完待更新~~

線段樹總結

線段樹總結 線段樹的原理就是每乙個區間都可以被分成若干個不相交連續區間 重要 線段樹維護的資料 1.自身結構的資料 比如 左兒子 右兒子的編號 2.懶惰標記 整段區間都變成乙個值 或者將要進行什麼操作 根據每次操作的型別 把操作的區間分成若干個不連續的區間 然後把操作的標記賦值給相應的區間 3.答案...

線段樹總結

線段樹的入門級 總結 線段樹是一種二叉搜尋樹,與區間樹相似,它將乙個區間劃分成一些單元區間,每個單元區間對應線段樹中的乙個葉結點。對於線段樹中的每乙個非葉子節點 a,b 它的左兒子表示的區間為 a,a b 2 右兒子表示的區間為 a b 2 1,b 因此線段樹是平衡二叉樹,最後的子節點數目為n,即整...

線段樹總結

解決的題目 對區間所對應的一些資料進行修改,查詢。基本步驟 先建樹,然後插入資料,然後更新,查詢。關鍵部分 用線段樹解題,關鍵是要想清楚每個節點要存哪些資訊以及這些資訊如何高效更新,維護,查詢。不要一更新就更新到葉子節點,那樣更新效率最壞就可能變成o n 的了。建樹的方式 1 陣列 若根節點下標為0...