kth number
劃分樹雖然可以做,但是**不好記。
看某人blog學習了主席樹的簡單操作。
引用某大牛的話來解釋一下主席樹:
所謂主席樹呢,就是對原來的數列[1..n]的每乙個字首[1..i](1≤i≤n)建立一棵線段樹,線段樹的每乙個節點存某個字首[1..i]中屬於區間[l..r]的數一共有多少個(比如根節點是[1..n],一共i個數,sum[root] = i;根節點的左兒子是[1..(l+r)/2],若不大於(l+r)/2的數有x個,那麼sum[root.left] = x)。若要查詢[i..j]中第k大數時,設某結點x,那麼x.sum[j] - x.sum[i - 1]就是[i..j]中在結點x內的數字總數。而對每乙個字首都建一棵樹,會mle,觀察到每個[1..i]和[1..i-1]只有一條路是不一樣的,那麼其他的結點只要用回前一棵樹的結點即可,時空複雜度為o(nlogn)。
——具體看**(有詳細注釋)
1 #include 2 #include 3view code#define lc son[now][0], l, mid
4#define rc son[now][1], mid + 1, r56
using
namespace
std;78
const
int n = 100000 + 5;9
10int
t, n, q, tot;
11int a[n], b[n], son[20 * n][2], sum[20 * n], rt[20 *n];
12//
主席樹第 i 棵樹存的是 a[0] - a[i] 的樹(字首和)
13//
主席樹乙個節點 sum 存的是當前線段所包含的數的個數。。暈。
14//
rt 是每一棵樹的根節點編號
15//
a 儲存原陣列,b 儲存排序後的陣列
1617
//注意 & 的使用
18 inline void build(int &now, int l, int
r)19
2728 inline void update(int &now, int l, int r, int last, int
x)29
4142
//因為每個節點存的是有多少個數在當前區間
43//
求區間 [1,3] 即求 rt[3] - rt[0] 內的數
44//
可通過遞迴二分解決
45 inline int query(int s, int t, int l, int r, int
x)46
5253
intmain()
5473}74
return0;
75 }
k-th number
——**
1 #include 2 #include 3view code#define debug puts("***********");45
const
int maxn = 100001;6
intn, m, cnt;
7int
b[maxn], root[maxn];
8struct
node
9p[maxn];
12struct
pst13
t[maxn * 20
];16
17 inline bool
cmp(node x, node y)
1821
22 inline void insert(int x, int &now, int l, int
r)23
3233 inline int query(int x, int y, int k, int l, int
r)34
4041
intmain()
4256
for(i = 1; i <= m; i++)
5761
return0;
62 }
主席樹 模板
思想 主席樹就是一顆持久化線段樹,為什麼叫持久化了,因為它可以儲存之前的線段樹版本,並且可以拿來用,從而優化空間.至於為什麼叫主席樹了,大概是因為發明這個演算法的人的名字的緣故吧 詳細說說 主席樹是一種離線資料結構,是由很多棵線段樹組成的。第i棵線段樹存的是前i個數的資訊 每乙個線段存數字的出現次數...
主席樹模板
維護n棵1 i的字首權值線段樹,每次查詢減一下就好了。poj 2104就是模板題,裸的靜態第k大,需要先離散化,不會的就用lower bound 多試試,研究研究應該就能懂。include include include include using namespace std const int m...
模板 主席樹
譴責奶人的hsz巨神 靜態版本 求區間第k大 可持久化也沒那麼高大上嘛,主席樹本質上就是多棵線段樹,求第k大就類似平衡樹的第k大。stay foolish,stay hungry,stay young,stay include include include include using namesp...