可持久化線段樹不是一顆完全二叉樹,所以不能用層次序編號,而應該直接記錄每個節點的左、右子節點的編號。可持久化線段樹維護了每次操作後線段樹的歷史形態。
下面舉個簡單的例子來理解一下:
以poj-2104為例;這棵樹是一顆不用修改的線段樹
題意:即多次查詢,查詢區間第k大的數。
//主席樹的學習--區間第k大
//區間第k大又可以用整體分治演算法,歸併樹,線段樹套平衡樹,主席樹來做
//以主席樹為例來做
#include#includeusing namespace std;
const int maxn = 1e5 + 5;
struct segmenttreetree[maxn * 30];
int tot, root[maxn];//主席樹的總點數和每個根
int a[maxn], b[maxn];//a用來存原數列,b用來存離散之後的
int n, m;
int cnt;
int build_tree(int l, int r)
*/ if (l == r)
int mid = (l + r) >> 1;
tree[step].lc = build_tree(l, mid);
tree[step].rc = build_tree(mid + 1, r);
tree[step].dat = tree[tree[step].lc].dat + tree[tree[step].rc].dat;
return step;
}int update(int rt, int pos, int val)
else
tree[step].dat = tree[rt].dat + val;
} return temp;
}int query(int r1, int r2, int k)
else
} return l;
}int main()
sort(b, b + n);
cnt = unique(b, b + n) - b;
tot = 0;
root[0] = build_tree(1, cnt);
for (int i = 1; i <= n; i++)
int l, r, k;
while (m--)
return 0;
}
poj2104 主席樹區間第k大
主席樹裸題,過了好久都快忘了。主席樹主要就是使多個線段樹並行於一顆樹中,儲存的是一段區間內數字出現的個數,所以先離散化。數字的更改只影響了一條從這個葉子節點到根的路徑,所以只有這條路徑是新的,其他的都沒有改變。比如對於某個節點,要往右邊走,那麼左邊那些就不用新建,只要用個指標鏈到原樹的此節點左邊就可...
poj 2104 主席樹 靜態區間第k大
主席樹入門題目,主席樹其實就是可持久化權值線段樹,rt i 維護了前i個數中第i大 小 的數出現次數的資訊,通過查詢兩棵樹的差即可得到第k大 小 元素。include include include using namespace std define lson i node i lson defi...
POJ 2104 區間第k大 主席樹(模板)
查詢區間範圍內,第 k kk 大的數 按照數列順序依次加入,構建可持久化線段樹 主席樹 由於線段樹的可減性,能夠得到對應區間範圍內的線段樹 主席樹的模板題了 int cnt,root maxn a maxn struct nodet maxn 40 vector int v intgetid int...